X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2FCmsApplication.java;h=f722befeb201007e59c3ecbe7c61313075279567;hb=51be851d1253d4858f9b63c533df6bcfe76a393f;hp=afb915d249d6c0426e9eb1710d2a7be2503a741a;hpb=998cdf60d00ffc35d987bdb373a9676b095f16f8;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 afb915d24..f722befeb 100644 --- a/org.argeo.cms/src/org/argeo/cms/CmsApplication.java +++ b/org.argeo.cms/src/org/argeo/cms/CmsApplication.java @@ -2,33 +2,55 @@ 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.internal.ImageManagerImpl; +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; -import org.springframework.osgi.context.BundleContextAware; /** Configures an Argeo CMS RWT application. */ public class CmsApplication implements CmsConstants, ApplicationConfiguration, BundleContextAware { final static Log log = LogFactory.getLog(CmsApplication.class); - private Map entryPoints = new HashMap(); - private Map> entryPointsBranding = new HashMap>(); + // private Map entryPoints = new HashMap(); + private Map> branding = new HashMap>(); private Map> styleSheets = new HashMap>(); private List resources = new ArrayList(); @@ -36,6 +58,22 @@ public class CmsApplication implements CmsConstants, ApplicationConfiguration, // 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 CmsLogin cmsLogin; + + 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 +87,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); + } - application.addEntryPoint("/" + entryPoint, - entryPoints.get(entryPoint), properties); - log.info("Registered entry point /" + entryPoint); + // page title + if (!properties.containsKey(WebClient.PAGE_TITLE)) + properties.put( + WebClient.PAGE_TITLE, + Character.toUpperCase(page.charAt(0)) + + page.substring(1)); + + // 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 +147,110 @@ 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 { +// if (workspace == null) +// throw new CmsException( +// "Workspace must be set when calling initialization." +// + " Please make sure that read-only and read-write roles" +// + " have been properly configured:" +// + " the defaults are open."); - private static ResourceLoader createResourceLoader(final String resourceName) { - return new ResourceLoader() { - public InputStream getResourceAsStream(String resourceName) - throws IOException { - return getClass().getClassLoader().getResourceAsStream( - resourceName); + 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); + } } - }; + + } finally { + JcrUtils.logoutQuietly(session); + } } - public void setEntryPoints( - Map entryPointFactories) { - this.entryPoints = entryPointFactories; + protected void initPage(Session adminSession, CmsUiProvider page) + throws RepositoryException { + if (page instanceof LifeCycleUiProvider) + ((LifeCycleUiProvider) page).init(adminSession); } - public void setEntryPointsBranding( - Map> entryPointBranding) { - this.entryPointsBranding = entryPointBranding; + 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 setStyleSheets(Map> styleSheets) { - this.styleSheets = styleSheets; + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setWorkspace(String workspace) { + this.workspace = workspace; } - // public void setClientScriptingBundle(Bundle clientScriptingBundle) { - // this.clientScriptingBundle = clientScriptingBundle; + public void setCmsLogin(CmsLogin cmsLogin) { + this.cmsLogin = cmsLogin; + } + + public void setHeader(CmsUiProvider header) { + this.header = header; + } + + public void setPages(Map pages) { + this.pages = pages; + } + + public void setBasePath(String basePath) { + this.basePath = basePath; + } + + 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 setEntryPoints( + // Map entryPointFactories) { + // this.entryPoints = entryPointFactories; // } + public void setBranding(Map> branding) { + this.branding = branding; + } + + public void setStyleSheets(Map> styleSheets) { + this.styleSheets = styleSheets; + } + public void setBundleContext(BundleContext bundleContext) { this.bundleContext = bundleContext; } @@ -173,25 +268,165 @@ 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 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 + 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)); + bodyArea.setBackgroundMode(SWT.INHERIT_DEFAULT); + bodyArea.setLayout(CmsUtils.noSpaceGridLayout()); + refreshBody(); + } catch (Exception e) { + throw new CmsException("Cannot create entrypoint contents", e); + } + } + + @Override + 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 - public PhaseId getPhaseId() { - return PhaseId.RENDER; + 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()); + // if (page == null) + // throw new CmsException("Page cannot be null"); + // // else if (state.length() == 0) + // // log.debug("empty state"); + // else if (pages.containsKey(page)) + // pages.get(page).createUi(bodyArea, getNode()); + // else { + // // try { + // // RWT.getResponse().sendError(404); + // // } catch (IOException e) { + // // log.error("Cannot send 404 code", e); + // // } + // throw new CmsException("Unsupported state " + state); + // } + } catch (RepositoryException e) { + throw new CmsException("Cannot refresh body", e); + } + } + bodyArea.layout(true, true); } @Override - public void beforePhase(PhaseEvent event) { - CmsSession cmsSession = CmsSession.current.get(); - String state = cmsSession.getState(); - if (state == null) - cmsSession.navigateTo("~"); + protected void logAsAnonymous() { + cmsLogin.logInAsAnonymous(); + } + + @Override + protected Node getDefaultNode(Session session) + throws RepositoryException { + if (!session.hasPermission(basePath, "read")) { + if (session.getUserID().equals("anonymous")) + throw new CmsLoginRequiredException(); + else + throw new CmsException("Unauthorized"); + } + return session.getNode(basePath); } @Override - public void afterPhase(PhaseEvent event) { + 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); + } + }; } /*