X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2FCmsApplication.java;h=9c7b5b3447ac707863a53047587ea36407f8fa85;hb=85ced0e58ded00f296948b6dff51f84994855080;hp=af8fa1c99fc25963aa302535afe16d34d7a0c6e0;hpb=4b56d461613392a3808d886d5373cf46b65a040e;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/CmsApplication.java b/org.argeo.cms/src/org/argeo/cms/CmsApplication.java index af8fa1c99..9c7b5b344 100644 --- a/org.argeo.cms/src/org/argeo/cms/CmsApplication.java +++ b/org.argeo.cms/src/org/argeo/cms/CmsApplication.java @@ -2,40 +2,75 @@ package org.argeo.cms; import java.io.IOException; import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.security.Privilege; +import javax.jcr.version.VersionManager; + +import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.argeo.cms.auth.LoginRequiredException; +import org.argeo.cms.internal.ImageManagerImpl; +import org.argeo.cms.util.BundleResourceLoader; +import org.argeo.cms.util.CmsUtils; +import org.argeo.jcr.JcrUtils; import org.eclipse.gemini.blueprint.context.BundleContextAware; +import org.eclipse.rap.rwt.RWT; 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.EntryPoint; import org.eclipse.rap.rwt.application.EntryPointFactory; import org.eclipse.rap.rwt.application.ExceptionHandler; import org.eclipse.rap.rwt.client.WebClient; -import org.eclipse.rap.rwt.lifecycle.PhaseEvent; -import org.eclipse.rap.rwt.lifecycle.PhaseId; -import org.eclipse.rap.rwt.lifecycle.PhaseListener; import org.eclipse.rap.rwt.service.ResourceLoader; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; import org.osgi.framework.BundleContext; /** Configures an Argeo CMS RWT application. */ public class CmsApplication implements CmsConstants, ApplicationConfiguration, BundleContextAware { - final static Log log = LogFactory.getLog(CmsApplication.class); + private final static Log log = LogFactory.getLog(CmsApplication.class); - private Map entryPoints = new HashMap(); - private Map> entryPointsBranding = new HashMap>(); + private Map> branding = new HashMap>(); private Map> styleSheets = new HashMap>(); private List resources = new ArrayList(); - // private Bundle clientScriptingBundle; private BundleContext bundleContext; + private Repository repository; + private String workspace = null; + private String basePath = "/"; + private List roPrincipals = Arrays.asList("anonymous", "everyone"); + private List rwPrincipals = Arrays.asList("everyone"); + + private CmsUiProvider header; + private Map pages = new LinkedHashMap(); + + private Integer headerHeight = 40; + + // Managers + private CmsImageManager imageManager = new ImageManagerImpl(); + public void configure(Application application) { try { application.setOperationMode(OperationMode.SWT_COMPATIBILITY); @@ -49,60 +84,58 @@ public class CmsApplication implements CmsConstants, ApplicationConfiguration, application.addResource(NO_IMAGE, createResourceLoader(NO_IMAGE)); for (String resource : resources) { - // URL res = bundleContext.getBundle().getResource(resource); - // if (res == null) - // throw new CmsException("Resource " + resource - // + " not found"); application.addResource(resource, new BundleResourceLoader( bundleContext)); if (log.isDebugEnabled()) log.debug("Registered resource " + resource); } + Map defaultBranding = null; + if (branding.containsKey("*")) + defaultBranding = branding.get("*"); + // entry points - for (String entryPoint : entryPoints.keySet()) { - Map properties = new HashMap(); - if (entryPointsBranding.containsKey(entryPoint)) { - properties = entryPointsBranding.get(entryPoint); - if (properties.containsKey(WebClient.FAVICON)) { - String faviconRelPath = properties - .get(WebClient.FAVICON); - // URL res = bundleContext.getBundle().getResource( - // faviconRelPath); - application.addResource(faviconRelPath, - new BundleResourceLoader(bundleContext)); - if (log.isTraceEnabled()) - log.trace("Registered favicon " + faviconRelPath); - - } - - if (!properties.containsKey(WebClient.BODY_HTML)) - properties.put(WebClient.BODY_HTML, - DEFAULT_LOADING_BODY); + for (String page : pages.keySet()) { + Map properties = defaultBranding != null ? new HashMap( + defaultBranding) : new HashMap(); + if (branding.containsKey(page)) { + properties.putAll(branding.get(page)); } + // favicon + if (properties.containsKey(WebClient.FAVICON)) { + String faviconRelPath = properties.get(WebClient.FAVICON); + application.addResource(faviconRelPath, + new BundleResourceLoader(bundleContext)); + if (log.isTraceEnabled()) + log.trace("Registered favicon " + faviconRelPath); + + } + + // page title + if (!properties.containsKey(WebClient.PAGE_TITLE)) + properties.put( + WebClient.PAGE_TITLE, + Character.toUpperCase(page.charAt(0)) + + page.substring(1)); - application.addEntryPoint("/" + entryPoint, - entryPoints.get(entryPoint), properties); - log.info("Registered entry point /" + entryPoint); + // default body HTML + if (!properties.containsKey(WebClient.BODY_HTML)) + properties.put(WebClient.BODY_HTML, DEFAULT_LOADING_BODY); + + application.addEntryPoint("/" + page, new CmsEntryPointFactory( + page), properties); + log.info("Registered entry point /" + page); } // stylesheets for (String themeId : styleSheets.keySet()) { List cssLst = styleSheets.get(themeId); for (String css : cssLst) { - // URL res = bundleContext.getBundle().getResource(css); - // if (res == null) - // throw new CmsException("Stylesheet " + css - // + " not found"); application.addStyleSheet(themeId, css, new BundleResourceLoader(bundleContext)); } } - - application.addPhaseListener(new CmsPhaseListener()); - - // registerClientScriptingResources(application); } catch (RuntimeException e) { // Easier access to initialisation errors log.error("Unexpected exception when configuring RWT application.", @@ -111,51 +144,100 @@ public class CmsApplication implements CmsConstants, ApplicationConfiguration, } } - // see Eclipse.org bug 369957 - // private void registerClientScriptingResources(Application application) { - // if (clientScriptingBundle != null) { - // String className = - // "org.eclipse.rap.clientscripting.internal.resources.ClientScriptingResources"; - // try { - // Class resourceClass = clientScriptingBundle - // .loadClass(className); - // Method registerMethod = resourceClass.getMethod("register", - // Application.class); - // registerMethod.invoke(null, application); - // } catch (Exception exception) { - // throw new RuntimeException(exception); - // } - // } - // } + public void init() throws RepositoryException { + Session session = null; + try { + session = JcrUtils.loginOrCreateWorkspace(repository, workspace); + VersionManager vm = session.getWorkspace().getVersionManager(); + if (!vm.isCheckedOut("/")) + vm.checkout("/"); + JcrUtils.mkdirs(session, basePath); + for (String principal : rwPrincipals) + JcrUtils.addPrivilege(session, basePath, principal, + Privilege.JCR_WRITE); + for (String principal : roPrincipals) + JcrUtils.addPrivilege(session, basePath, principal, + Privilege.JCR_READ); + + for (String pageName : pages.keySet()) { + try { + initPage(session, pages.get(pageName)); + session.save(); + } catch (Exception e) { + throw new CmsException( + "Cannot initialize page " + pageName, e); + } + } - private static ResourceLoader createResourceLoader(final String resourceName) { - return new ResourceLoader() { - public InputStream getResourceAsStream(String resourceName) - throws IOException { - return getClass().getClassLoader().getResourceAsStream( - resourceName); + } finally { + JcrUtils.logoutQuietly(session); + } + } + + protected void initPage(Session adminSession, CmsUiProvider page) + throws RepositoryException { + if (page instanceof LifeCycleUiProvider) + ((LifeCycleUiProvider) page).init(adminSession); + } + + public void destroy() { + for (String pageName : pages.keySet()) { + try { + CmsUiProvider page = pages.get(pageName); + if (page instanceof LifeCycleUiProvider) + ((LifeCycleUiProvider) page).destroy(); + } catch (Exception e) { + log.error("Cannot destroy page " + pageName, e); } - }; + } + } + + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setWorkspace(String workspace) { + this.workspace = workspace; + } + + public void setCmsLogin(@SuppressWarnings("deprecation") CmsLogin cmsLogin) { + // this.cmsLogin = cmsLogin; + log.warn("cmsLogin" + + " is deprecated and will be removed soon. Adapt your configuration ASAP."); + } + + public void setHeader(CmsUiProvider header) { + this.header = header; + } + + public void setPages(Map pages) { + this.pages = pages; } - public void setEntryPoints( - Map entryPointFactories) { - this.entryPoints = entryPointFactories; + public void setBasePath(String basePath) { + this.basePath = basePath; } - public void setEntryPointsBranding( - Map> entryPointBranding) { - this.entryPointsBranding = entryPointBranding; + public void setRoPrincipals(List roPrincipals) { + this.roPrincipals = roPrincipals; + } + + public void setRwPrincipals(List rwPrincipals) { + this.rwPrincipals = rwPrincipals; + } + + public void setHeaderHeight(Integer headerHeight) { + this.headerHeight = headerHeight; + } + + public void setBranding(Map> branding) { + this.branding = branding; } public void setStyleSheets(Map> styleSheets) { this.styleSheets = styleSheets; } - // public void setClientScriptingBundle(Bundle clientScriptingBundle) { - // this.clientScriptingBundle = clientScriptingBundle; - // } - public void setBundleContext(BundleContext bundleContext) { this.bundleContext = bundleContext; } @@ -173,25 +255,148 @@ public class CmsApplication implements CmsConstants, ApplicationConfiguration, } - class CmsPhaseListener implements PhaseListener { - private static final long serialVersionUID = -1966645586738534609L; + private class CmsEntryPointFactory implements EntryPointFactory { + private final String page; + + public CmsEntryPointFactory(String page) { + this.page = page; + } @Override - public PhaseId getPhaseId() { - return PhaseId.RENDER; + public EntryPoint create() { + CmsEntryPoint entryPoint = new CmsEntryPoint(repository, workspace, + pages.get(page)); + entryPoint.setState(""); + CmsSession.current.set(entryPoint); + return entryPoint; + } + + } + + private class CmsEntryPoint extends AbstractCmsEntryPoint { + private Composite headerArea; + private Composite bodyArea; + private final CmsUiProvider uiProvider; + + public CmsEntryPoint(Repository repository, String workspace, + CmsUiProvider uiProvider) { + super(repository, workspace); + this.uiProvider = uiProvider; } @Override - public void beforePhase(PhaseEvent event) { - CmsSession cmsSession = CmsSession.current.get(); - String state = cmsSession.getState(); - if (state == null) - cmsSession.navigateTo("~"); + protected void createContents(Composite parent) { + try { + getShell().getDisplay().setData(CmsSession.KEY, this); + + parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, + true)); + parent.setLayout(CmsUtils.noSpaceGridLayout()); + + headerArea = new Composite(parent, SWT.NONE); + headerArea.setLayout(new FillLayout()); + GridData headerData = new GridData(SWT.FILL, SWT.FILL, false, + false); + headerData.heightHint = headerHeight; + headerArea.setLayoutData(headerData); + refreshHeader(); + + bodyArea = new Composite(parent, SWT.NONE); + bodyArea.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_BODY); + bodyArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, + true)); + // Should not be set here: it then prevent all children + // composite to define a background color via CSS + // bodyArea.setBackgroundMode(SWT.INHERIT_DEFAULT); + bodyArea.setLayout(CmsUtils.noSpaceGridLayout()); + refreshBody(); + } catch (Exception e) { + throw new CmsException("Cannot create entrypoint contents", e); + } } @Override - public void afterPhase(PhaseEvent event) { + protected void refreshHeader() { + if (headerArea == null) + return; + for (Control child : headerArea.getChildren()) + child.dispose(); + try { + header.createUi(headerArea, getNode()); + } catch (RepositoryException e) { + throw new CmsException("Cannot refresh header", e); + } + headerArea.layout(true, true); } + + @Override + protected void refreshBody() { + if (bodyArea == null) + return; + // clear + for (Control child : bodyArea.getChildren()) + child.dispose(); + bodyArea.setLayout(CmsUtils.noSpaceGridLayout()); + + // Exception + Throwable exception = getException(); + if (exception != null) { + new Label(bodyArea, SWT.NONE).setText("Unreachable state : " + + getState()); + if (getNode() != null) + new Label(bodyArea, SWT.NONE).setText("Context : " + + getNode()); + + Text errorText = new Text(bodyArea, SWT.MULTI | SWT.H_SCROLL + | SWT.V_SCROLL); + errorText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, + true)); + StringWriter sw = new StringWriter(); + exception.printStackTrace(new PrintWriter(sw)); + errorText.setText(sw.toString()); + IOUtils.closeQuietly(sw); + resetException(); + // TODO report + } else { + String state = getState(); + try { + if (state == null) + throw new CmsException("State cannot be null"); + uiProvider.createUi(bodyArea, getNode()); + } catch (RepositoryException e) { + throw new CmsException("Cannot refresh body", e); + } + } + bodyArea.layout(true, true); + } + + @Override + protected Node getDefaultNode(Session session) + throws RepositoryException { + if (!session.hasPermission(basePath, "read")) { + if (session.getUserID().equals("anonymous")) + throw new LoginRequiredException(); + else + throw new CmsException("Unauthorized"); + } + return session.getNode(basePath); + } + + @Override + public CmsImageManager getImageManager() { + return imageManager; + } + + } + + private static ResourceLoader createResourceLoader(final String resourceName) { + return new ResourceLoader() { + public InputStream getResourceAsStream(String resourceName) + throws IOException { + return getClass().getClassLoader().getResourceAsStream( + resourceName); + } + }; } /*