From: Mathieu Baudier Date: Fri, 8 May 2015 15:46:44 +0000 (+0000) Subject: Introduce SimpleApp and SimpleErgonomics X-Git-Tag: argeo-commons-2.1.30~250 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=ba85380c1db977b0d9ea3182d1383956a8b80679;p=lgpl%2Fargeo-commons.git Introduce SimpleApp and SimpleErgonomics git-svn-id: https://svn.argeo.org/commons/trunk@8102 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/org.argeo.cms/src/org/argeo/cms/AbstractCmsEntryPoint.java b/org.argeo.cms/src/org/argeo/cms/AbstractCmsEntryPoint.java index d3d4cbe90..9a7f6412e 100644 --- a/org.argeo.cms/src/org/argeo/cms/AbstractCmsEntryPoint.java +++ b/org.argeo.cms/src/org/argeo/cms/AbstractCmsEntryPoint.java @@ -18,6 +18,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; import org.argeo.cms.auth.ArgeoLoginContext; +import org.argeo.cms.auth.LoginRequiredException; import org.argeo.cms.i18n.Msg; import org.argeo.jcr.JcrUtils; import org.eclipse.rap.rwt.RWT; @@ -27,22 +28,24 @@ import org.eclipse.rap.rwt.client.service.BrowserNavigation; import org.eclipse.rap.rwt.client.service.BrowserNavigationEvent; import org.eclipse.rap.rwt.client.service.BrowserNavigationListener; import org.eclipse.rap.rwt.client.service.JavaScriptExecutor; +import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; /** Manages history and navigation */ -abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements - CmsSession { +public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint + implements CmsSession { private final Log log = LogFactory.getLog(AbstractCmsEntryPoint.class); - private Subject subject = new Subject(); + private final Subject subject = new Subject(); - private Repository repository; - private String workspace; - private Session session; + private final Repository repository; + private final String workspace; + private final String defaultPath; private final Map factoryProperties; - // current state + // Current state + private Session session; private Node node; private String state; private String page; @@ -53,9 +56,10 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements private final BrowserNavigation browserNavigation; public AbstractCmsEntryPoint(Repository repository, String workspace, - Map factoryProperties) { + String defaultPath, Map factoryProperties) { this.repository = repository; this.workspace = workspace; + this.defaultPath = defaultPath; this.factoryProperties = new HashMap(factoryProperties); // Initial login @@ -80,8 +84,6 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements if (browserNavigation != null) browserNavigation .addBrowserNavigationListener(new CmsNavigationListener()); - - // RWT.setLocale(Locale.FRANCE); } @Override @@ -100,32 +102,36 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements return shell; } - /** Recreate header UI */ - protected abstract void refreshHeader(); + @Override + protected final void createContents(Composite parent) { + try { + getShell().getDisplay().setData(CmsSession.KEY, this); + + createUi(parent); + } catch (Exception e) { + throw new CmsException("Cannot create entrypoint contents", e); + } + } + + /** Create UI */ + protected abstract void createUi(Composite parent); - /** Recreate body UI */ - protected abstract void refreshBody(); + /** Recreate UI after navigation or auth change */ + protected abstract void refresh(); /** * The node to return when no node was found (for authenticated users and * anonymous) */ - protected abstract Node getDefaultNode(Session session) - throws RepositoryException; - - /** - * Reasonable default since it is a nt:hierarchyNode and is thus compatible - * with the obvious default folder type, nt:folder, conceptual equivalent of - * an empty text file in an operating system. To be overridden. - */ - // protected String getDefaultNewNodeType() { - // return CmsTypes.CMS_TEXT; - // } - - /** Default new folder type (used in mkdirs) is nt:folder. To be overridden. */ - // protected String getDefaultNewFolderType() { - // return NodeType.NT_FOLDER; - // } + protected Node getDefaultNode(Session session) throws RepositoryException { + if (!session.hasPermission(defaultPath, "read")) { + if (session.getUserID().equals("anonymous")) + throw new LoginRequiredException(); + else + throw new CmsException("Unauthorized"); + } + return session.getNode(defaultPath); + } protected String getBaseTitle() { return factoryProperties.get(WebClient.PAGE_TITLE); @@ -134,7 +140,7 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements public void navigateTo(String state) { exception = null; String title = setState(state); - refreshBody(); + refresh(); if (browserNavigation != null) browserNavigation.pushState(state, title); } @@ -157,8 +163,7 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements node = session.getNode(currentPath); // refresh UI - refreshHeader(); - refreshBody(); + refresh(); } catch (RepositoryException e) { throw new CmsException("Cannot perform auth change", e); } @@ -169,7 +174,7 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements public void exception(Throwable e) { this.exception = e; log.error("Unexpected exception in CMS", e); - refreshBody(); + refresh(); } @Override @@ -205,34 +210,10 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements } else if (firstSlash > 0) { String prefix = state.substring(0, firstSlash); String path = state.substring(firstSlash); - // if (session.getWorkspace().getNodeTypeManager() - // .hasNodeType(prefix)) { - // String nodeType = prefix; - // if (!session.nodeExists(path)) - // node = addNode(session, path, nodeType); - // else { - // node = session.getNode(path); - // if (!node.isNodeType(nodeType)) - // throw new CmsException("Node " + path - // + " not of type " + nodeType); - // } - // } else if ("delete".equals(prefix)) { - // if (session.itemExists(path)) { - // Node nodeToDelete = session.getNode(path); - // // TODO "Are you sure?" - // nodeToDelete.remove(); - // session.save(); - // log.debug("Deleted " + path); - // navigateTo(previousState); - // } else - // throw new CmsException("Data " + path - // + " does not exist"); - // } else { if (session.nodeExists(path)) node = session.getNode(path); else throw new CmsException("Data " + path + " does not exist"); - // } page = prefix; } else { node = getDefaultNode(session); @@ -255,6 +236,7 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements return title; } catch (Exception e) { + log.error("Cannot set state '" + state + "'", e); if (previousState.equals("")) previousState = "~"; navigateTo(previousState); @@ -263,13 +245,6 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements } } - // protected Node addNode(Session session, String path, String nodeType) - // throws RepositoryException { - // return JcrUtils.mkdirs(session, path, nodeType != null ? nodeType - // : getDefaultNewNodeType(), getDefaultNewFolderType(), false); - // // not saved, so that the UI can discard it later on - // } - protected Node getNode() { return node; } @@ -278,10 +253,6 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements return state; } - // String getPage() { - // return page; - // } - protected Throwable getException() { return exception; } @@ -300,8 +271,7 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements @Override public void navigated(BrowserNavigationEvent event) { setState(event.getState()); - refreshBody(); + refresh(); } } - -} +} \ No newline at end of file diff --git a/org.argeo.cms/src/org/argeo/cms/CmsApplication.java b/org.argeo.cms/src/org/argeo/cms/CmsApplication.java index 2f2697d5a..c428a0bf9 100644 --- a/org.argeo.cms/src/org/argeo/cms/CmsApplication.java +++ b/org.argeo.cms/src/org/argeo/cms/CmsApplication.java @@ -1,422 +1,405 @@ package org.argeo.cms; -import java.io.IOException; -import java.io.InputStream; -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.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.cms.util.SystemNotifications; -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.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.osgi.framework.BundleContext; - -/** Configures an Argeo CMS RWT application. */ -public class CmsApplication implements CmsConstants, ApplicationConfiguration, - BundleContextAware { +import org.argeo.cms.util.SimpleApp; + +/** + * Configures an Argeo CMS RWT application. + * + * @deprecated Use {@link SimpleApp} instead (same method signatures) + */ +@Deprecated +public class CmsApplication extends SimpleApp { private final static Log log = LogFactory.getLog(CmsApplication.class); - private Map> branding = new HashMap>(); - private Map> styleSheets = new HashMap>(); - - private List resources = new ArrayList(); - - 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); - application.setExceptionHandler(new CmsExceptionHandler()); - - // TODO load all pics under icons - // loading animated gif - application.addResource(LOADING_IMAGE, - createResourceLoader(LOADING_IMAGE)); - // empty image - application.addResource(NO_IMAGE, createResourceLoader(NO_IMAGE)); - - for (String resource : resources) { - 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 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)); - - // default body HTML - if (!properties.containsKey(WebClient.BODY_HTML)) - properties.put(WebClient.BODY_HTML, DEFAULT_LOADING_BODY); - - // - // ADD ENTRY POINT - // - application.addEntryPoint("/" + page, new CmsEntryPointFactory( - pages.get(page), repository, workspace, properties), - properties); - log.info("Registered entry point /" + page); - } - - // stylesheets - for (String themeId : styleSheets.keySet()) { - List cssLst = styleSheets.get(themeId); - for (String css : cssLst) { - application.addStyleSheet(themeId, css, - new BundleResourceLoader(bundleContext)); - } - - } - } catch (RuntimeException e) { - // Easier access to initialisation errors - log.error("Unexpected exception when configuring RWT application.", - e); - throw e; - } - } - - 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); - } - } - - } 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 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 setBranding(Map> branding) { - this.branding = branding; - } - - public void setStyleSheets(Map> styleSheets) { - this.styleSheets = styleSheets; - } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - - public void setResources(List resources) { - this.resources = resources; - } - - class CmsExceptionHandler implements ExceptionHandler { - - @Override - public void handleException(Throwable throwable) { - CmsSession.current.get().exception(throwable); - } - - } - - private class CmsEntryPointFactory implements EntryPointFactory { - private final CmsUiProvider page; - private final Repository repository; - private final String workspace; - private final Map properties; - - public CmsEntryPointFactory(CmsUiProvider page, Repository repository, - String workspace, Map properties) { - this.page = page; - this.repository = repository; - this.workspace = workspace; - this.properties = properties; - } - - @Override - public EntryPoint create() { - CmsEntryPoint entryPoint = new CmsEntryPoint(repository, workspace, - page, properties); - 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, Map factoryProperties) { - super(repository, workspace, factoryProperties); - 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)); - // 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 - 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; - // 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); - SystemNotifications systemNotifications = new SystemNotifications( - bodyArea); - systemNotifications.notifyException(exception); - resetException(); - return; - // TODO report - } - - // clear - for (Control child : bodyArea.getChildren()) - child.dispose(); - bodyArea.setLayout(CmsUtils.noSpaceGridLayout()); - - 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); - } - }; + public CmsApplication() { + super(); + log.warn("org.argeo.cms.CmsApplication will be removed soon, use org.argeo.cms.util.SimpleApp"); } - /* - * TEXTS - */ - private static String DEFAULT_LOADING_BODY = "" - + "" - + ""; + // + // private Map> branding = new HashMap>(); + // private Map> styleSheets = new HashMap>(); + // + // private List resources = new ArrayList(); + // + // 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); + // application.setExceptionHandler(new CmsExceptionHandler()); + // + // // TODO load all pics under icons + // // loading animated gif + // application.addResource(LOADING_IMAGE, + // createResourceLoader(LOADING_IMAGE)); + // // empty image + // application.addResource(NO_IMAGE, createResourceLoader(NO_IMAGE)); + // + // for (String resource : resources) { + // 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 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)); + // + // // default body HTML + // if (!properties.containsKey(WebClient.BODY_HTML)) + // properties.put(WebClient.BODY_HTML, DEFAULT_LOADING_BODY); + // + // // + // // ADD ENTRY POINT + // // + // application.addEntryPoint("/" + page, new CmsEntryPointFactory( + // pages.get(page), repository, workspace, properties), + // properties); + // log.info("Registered entry point /" + page); + // } + // + // // stylesheets + // for (String themeId : styleSheets.keySet()) { + // List cssLst = styleSheets.get(themeId); + // for (String css : cssLst) { + // application.addStyleSheet(themeId, css, + // new BundleResourceLoader(bundleContext)); + // } + // + // } + // } catch (RuntimeException e) { + // // Easier access to initialisation errors + // log.error("Unexpected exception when configuring RWT application.", + // e); + // throw e; + // } + // } + // + // 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); + // } + // } + // + // } 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 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 setBranding(Map> branding) { + // this.branding = branding; + // } + // + // public void setStyleSheets(Map> styleSheets) { + // this.styleSheets = styleSheets; + // } + // + // public void setBundleContext(BundleContext bundleContext) { + // this.bundleContext = bundleContext; + // } + // + // public void setResources(List resources) { + // this.resources = resources; + // } + // + // class CmsExceptionHandler implements ExceptionHandler { + // + // @Override + // public void handleException(Throwable throwable) { + // CmsSession.current.get().exception(throwable); + // } + // + // } + // + // private class CmsEntryPointFactory implements EntryPointFactory { + // private final CmsUiProvider page; + // private final Repository repository; + // private final String workspace; + // private final Map properties; + // + // public CmsEntryPointFactory(CmsUiProvider page, Repository repository, + // String workspace, Map properties) { + // this.page = page; + // this.repository = repository; + // this.workspace = workspace; + // this.properties = properties; + // } + // + // @Override + // public EntryPoint create() { + // CmsEntryPoint entryPoint = new CmsEntryPoint(repository, workspace, + // page, properties); + // 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, Map factoryProperties) { + // super(repository, workspace, factoryProperties); + // 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)); + // // 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 + // 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; + // // 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); + // SystemNotifications systemNotifications = new SystemNotifications( + // bodyArea); + // systemNotifications.notifyException(exception); + // resetException(); + // return; + // // TODO report + // } + // + // // clear + // for (Control child : bodyArea.getChildren()) + // child.dispose(); + // bodyArea.setLayout(CmsUtils.noSpaceGridLayout()); + // + // 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); + // } + // }; + // } + // + // /* + // * TEXTS + // */ + // private static String DEFAULT_LOADING_BODY = "" + // + + // "" + // + ""; } diff --git a/org.argeo.cms/src/org/argeo/cms/CmsLogin.java b/org.argeo.cms/src/org/argeo/cms/CmsLogin.java deleted file mode 100644 index a9dd8255f..000000000 --- a/org.argeo.cms/src/org/argeo/cms/CmsLogin.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.argeo.cms; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.cms.auth.ArgeoLoginContext; -import org.springframework.security.authentication.AuthenticationManager; - -/** - * Gateway for user login, can also generate the related UI. - * - * @deprecated Use {@link ArgeoLoginContext} instead - */ -@Deprecated -public class CmsLogin { - private final static Log log = LogFactory.getLog(CmsLogin.class); - - public CmsLogin() { - log.warn("org.argeo.cms.CmsLogin is deprecated and will be removed soon."); - } - - // private AuthenticationManager authenticationManager; - // - // public void logInAsAnonymous() { - // Subject subject = new Subject(); - // final LoginContext loginContext; - // try { - // loginContext = new ArgeoLoginContext( - // KernelHeader.LOGIN_CONTEXT_ANONYMOUS, subject); - // loginContext.login(); - // } catch (LoginException e1) { - // throw new ArgeoException("Cannot authenticate anonymous", e1); - // } - // } - // - // public void logInWithPassword(String username, char[] password) { - // NodeAuthenticationToken token = new NodeAuthenticationToken(username, - // password); - // Authentication authentication = authenticationManager - // .authenticate(token); - // SecurityContextHolder.getContext().setAuthentication(authentication); - // if (log.isDebugEnabled()) - // log.debug("Authenticated as " + authentication); - // } - // - public void setAuthenticationManager( - AuthenticationManager authenticationManager) { - // this.authenticationManager = authenticationManager; - } -} diff --git a/org.argeo.cms/src/org/argeo/cms/util/OpenUserMenu.java b/org.argeo.cms/src/org/argeo/cms/util/OpenUserMenu.java index 8ad15bf9c..bb2bb3990 100644 --- a/org.argeo.cms/src/org/argeo/cms/util/OpenUserMenu.java +++ b/org.argeo.cms/src/org/argeo/cms/util/OpenUserMenu.java @@ -1,30 +1,17 @@ package org.argeo.cms.util; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.cms.CmsLogin; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.widgets.Control; /** Open the user menu when clicked */ -@SuppressWarnings("deprecation") public class OpenUserMenu extends MouseAdapter { private static final long serialVersionUID = 3634864186295639792L; - private final static Log log = LogFactory.getLog(OpenUserMenu.class); - - // private CmsLogin cmsLogin; - @Override public void mouseDown(MouseEvent e) { if (e.button == 1) { new UserMenu((Control) e.getSource()); } } - - public void setCmsLogin(CmsLogin cmsLogin) { - log.warn("org.argeo.cms.CmsLogin is deprecated and will be removed soon"); - } - } \ No newline at end of file diff --git a/org.argeo.cms/src/org/argeo/cms/util/SimpleApp.java b/org.argeo.cms/src/org/argeo/cms/util/SimpleApp.java new file mode 100644 index 000000000..be764e975 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/util/SimpleApp.java @@ -0,0 +1,295 @@ +package org.argeo.cms.util; + +import java.io.IOException; +import java.io.InputStream; +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.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.security.Privilege; +import javax.jcr.version.VersionManager; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.cms.CmsConstants; +import org.argeo.cms.CmsException; +import org.argeo.cms.CmsSession; +import org.argeo.cms.CmsUiProvider; +import org.argeo.cms.LifeCycleUiProvider; +import org.argeo.jcr.JcrUtils; +import org.eclipse.gemini.blueprint.context.BundleContextAware; +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.service.ResourceLoader; +import org.osgi.framework.BundleContext; + +/** A basic generic app based on {@link SimpleErgonomics}. */ +public class SimpleApp implements CmsConstants, ApplicationConfiguration, + BundleContextAware { + private final static Log log = LogFactory.getLog(SimpleApp.class); + + private Map> branding = new HashMap>(); + private Map> styleSheets = new HashMap>(); + + private List resources = new ArrayList(); + + 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; + + public void configure(Application application) { + try { + application.setOperationMode(OperationMode.SWT_COMPATIBILITY); + application.setExceptionHandler(new CmsExceptionHandler()); + + // loading animated gif + application.addResource(LOADING_IMAGE, + createResourceLoader(LOADING_IMAGE)); + // empty image + application.addResource(NO_IMAGE, createResourceLoader(NO_IMAGE)); + + for (String resource : resources) { + 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 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)); + + // default body HTML + if (!properties.containsKey(WebClient.BODY_HTML)) + properties.put(WebClient.BODY_HTML, DEFAULT_LOADING_BODY); + + // + // ADD ENTRY POINT + // + application.addEntryPoint("/" + page, new CmsEntryPointFactory( + pages.get(page), repository, workspace, properties), + properties); + log.info("Registered entry point /" + page); + } + + // stylesheets + for (String themeId : styleSheets.keySet()) { + List cssLst = styleSheets.get(themeId); + for (String css : cssLst) { + application.addStyleSheet(themeId, css, + new BundleResourceLoader(bundleContext)); + } + + } + } catch (RuntimeException e) { + // Easier access to initialisation errors + log.error("Unexpected exception when configuring RWT application.", + e); + throw e; + } + } + + 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); + } + } + + } 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 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 setBranding(Map> branding) { + this.branding = branding; + } + + public void setStyleSheets(Map> styleSheets) { + this.styleSheets = styleSheets; + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + public void setResources(List resources) { + this.resources = resources; + } + + class CmsExceptionHandler implements ExceptionHandler { + + @Override + public void handleException(Throwable throwable) { + CmsSession.current.get().exception(throwable); + } + + } + + private class CmsEntryPointFactory implements EntryPointFactory { + private final CmsUiProvider page; + private final Repository repository; + private final String workspace; + private final Map properties; + + public CmsEntryPointFactory(CmsUiProvider page, Repository repository, + String workspace, Map properties) { + this.page = page; + this.repository = repository; + this.workspace = workspace; + this.properties = properties; + } + + @Override + public EntryPoint create() { + SimpleErgonomics entryPoint = new SimpleErgonomics(repository, + workspace, basePath, page, properties); + // entryPoint.setState(""); + entryPoint.setHeader(header); + entryPoint.setHeaderHeight(headerHeight); + CmsSession.current.set(entryPoint); + return entryPoint; + } + + } + + private static ResourceLoader createResourceLoader(final String resourceName) { + return new ResourceLoader() { + public InputStream getResourceAsStream(String resourceName) + throws IOException { + return getClass().getClassLoader().getResourceAsStream( + resourceName); + } + }; + } + + // private static ResourceLoader createUrlResourceLoader(final URL url) { + // return new ResourceLoader() { + // public InputStream getResourceAsStream(String resourceName) + // throws IOException { + // return url.openStream(); + // } + // }; + // } + + /* + * TEXTS + */ + private static String DEFAULT_LOADING_BODY = "" + + "" + + ""; +} diff --git a/org.argeo.cms/src/org/argeo/cms/util/SimpleErgonomics.java b/org.argeo.cms/src/org/argeo/cms/util/SimpleErgonomics.java new file mode 100644 index 000000000..4b871cbcf --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/util/SimpleErgonomics.java @@ -0,0 +1,125 @@ +package org.argeo.cms.util; + +import java.util.Map; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; + +import org.argeo.cms.AbstractCmsEntryPoint; +import org.argeo.cms.CmsException; +import org.argeo.cms.CmsImageManager; +import org.argeo.cms.CmsStyles; +import org.argeo.cms.CmsUiProvider; +import org.argeo.cms.internal.ImageManagerImpl; +import org.eclipse.rap.rwt.RWT; +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; + +/** Simple header/body ergonomics. */ +public class SimpleErgonomics extends AbstractCmsEntryPoint { + private Composite headerArea; + private Composite bodyArea; + private final CmsUiProvider uiProvider; + + private CmsUiProvider header; + private Integer headerHeight = 40; + + private CmsImageManager imageManager = new ImageManagerImpl(); + + public SimpleErgonomics(Repository repository, String workspace, + String defaultPath, CmsUiProvider uiProvider, + Map factoryProperties) { + super(repository, workspace, defaultPath, factoryProperties); + this.uiProvider = uiProvider; + } + + @Override + protected void createUi(Composite parent) { + 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); + + 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.setLayout(CmsUtils.noSpaceGridLayout()); + + refresh(); + } + + @Override + protected void refresh() { + refreshHeader(); + refreshBody(); + } + + 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); + } + + protected void refreshBody() { + if (bodyArea == null) + return; + // Exception + Throwable exception = getException(); + if (exception != null) { + SystemNotifications systemNotifications = new SystemNotifications( + bodyArea); + systemNotifications.notifyException(exception); + resetException(); + return; + // TODO report + } + + // clear + for (Control child : bodyArea.getChildren()) + child.dispose(); + bodyArea.setLayout(CmsUtils.noSpaceGridLayout()); + + String state = getState(); + try { + if (state == null) + setState(""); + // 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 + public CmsImageManager getImageManager() { + return imageManager; + } + + public void setHeader(CmsUiProvider header) { + this.header = header; + } + + public void setHeaderHeight(Integer headerHeight) { + this.headerHeight = headerHeight; + } + + public void setImageManager(CmsImageManager imageManager) { + this.imageManager = imageManager; + } +}