From: Mathieu Baudier Date: Sun, 5 Dec 2021 07:10:27 +0000 (+0100) Subject: Prepare JCR decoupling. X-Git-Tag: argeo-commons-2.3.5~134 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=a1e5c8447beec2b896b0a03e38a4c17608a4b85d;p=lgpl%2Fargeo-commons.git Prepare JCR decoupling. --- diff --git a/org.argeo.api/src/org/argeo/api/NodeDeployment.java b/org.argeo.api/src/org/argeo/api/NodeDeployment.java index d678bac0b..35436a8c3 100644 --- a/org.argeo.api/src/org/argeo/api/NodeDeployment.java +++ b/org.argeo.api/src/org/argeo/api/NodeDeployment.java @@ -1,6 +1,12 @@ package org.argeo.api; +import java.util.Dictionary; + /** A configured node deployment. */ public interface NodeDeployment { Long getAvailableSince(); + + void addFactoryDeployConfig(String factoryPid, Dictionary props); + Dictionary getProps(String factoryPid, String cn); + } diff --git a/org.argeo.cms/src/org/argeo/cms/CmsUserManager.java b/org.argeo.cms/src/org/argeo/cms/CmsUserManager.java index 1dafe7c81..d970855ff 100644 --- a/org.argeo.cms/src/org/argeo/cms/CmsUserManager.java +++ b/org.argeo.cms/src/org/argeo/cms/CmsUserManager.java @@ -4,7 +4,6 @@ import java.time.ZonedDateTime; import java.util.List; import java.util.Set; -import javax.jcr.Node; import javax.security.auth.Subject; import javax.transaction.UserTransaction; @@ -80,7 +79,7 @@ public interface CmsUserManager { void expireAuthTokens(Subject subject); - User createUserFromPerson(Node person); +// User createUserFromPerson(Node person); @Deprecated public UserAdmin getUserAdmin(); diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CmsSession.java b/org.argeo.cms/src/org/argeo/cms/auth/CmsSession.java index a0ea6a63f..ad91cb7f0 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/CmsSession.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/CmsSession.java @@ -29,6 +29,8 @@ public interface CmsSession { String getLocalId(); Authorization getAuthorization(); + + Subject getSubject(); boolean isAnonymous(); diff --git a/org.argeo.cms/src/org/argeo/cms/cli/ArgeoCli.java b/org.argeo.cms/src/org/argeo/cms/cli/ArgeoCli.java index fbac64dc9..b8eafca86 100644 --- a/org.argeo.cms/src/org/argeo/cms/cli/ArgeoCli.java +++ b/org.argeo.cms/src/org/argeo/cms/cli/ArgeoCli.java @@ -3,7 +3,6 @@ package org.argeo.cms.cli; import org.apache.commons.cli.Option; import org.argeo.cli.CommandsCli; import org.argeo.cli.fs.FsCommands; -import org.argeo.cli.jcr.JcrCommands; import org.argeo.cli.posix.PosixCommands; /** Argeo command line tools. */ @@ -18,7 +17,7 @@ public class ArgeoCli extends CommandsCli { addCommandsCli(new PosixCommands("posix")); addCommandsCli(new FsCommands("fs")); - addCommandsCli(new JcrCommands("jcr")); +// addCommandsCli(new JcrCommands("jcr")); } @Override diff --git a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java index f40c6fffd..734b874ef 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java @@ -4,12 +4,9 @@ import java.io.Serializable; import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.time.ZonedDateTime; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Hashtable; import java.util.Locale; import java.util.Map; @@ -17,8 +14,6 @@ import java.util.Set; import java.util.UUID; import javax.crypto.SecretKey; -import javax.jcr.Repository; -import javax.jcr.Session; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; import javax.security.auth.Subject; @@ -31,7 +26,6 @@ import org.apache.commons.logging.LogFactory; import org.argeo.api.NodeConstants; import org.argeo.api.security.NodeSecurityUtils; import org.argeo.cms.auth.CmsSession; -import org.argeo.jcr.JcrUtils; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.InvalidSyntaxException; @@ -59,10 +53,6 @@ public class CmsSessionImpl implements CmsSession, Serializable { private ServiceRegistration serviceRegistration; - private Map dataSessions = new HashMap<>(); - private Set dataSessionsInUse = new HashSet<>(); - private Set additionalDataSessions = new HashSet<>(); - private Map views = new HashMap<>(); public CmsSessionImpl(Subject initialSubject, Authorization authorization, Locale locale, String localSessionId) { @@ -103,13 +93,6 @@ public class CmsSessionImpl implements CmsSession, Serializable { end = ZonedDateTime.now(); serviceRegistration.unregister(); - synchronized (this) { - // TODO check data session in use ? - for (String path : dataSessions.keySet()) - JcrUtils.logoutQuietly(dataSessions.get(path)); - for (Session session : additionalDataSessions) - JcrUtils.logoutQuietly(session); - } try { LoginContext lc; @@ -127,7 +110,7 @@ public class CmsSessionImpl implements CmsSession, Serializable { log.debug("Closed " + this); } - private Subject getSubject() { + public Subject getSubject() { return Subject.getSubject(accessControlContext); } @@ -136,78 +119,6 @@ public class CmsSessionImpl implements CmsSession, Serializable { return getSubject().getPrivateCredentials(SecretKey.class); } - public Session newDataSession(String cn, String workspace, Repository repository) { - checkValid(); - return login(repository, workspace); - } - - public synchronized Session getDataSession(String cn, String workspace, Repository repository) { - checkValid(); - // FIXME make it more robust - if (workspace == null) - workspace = NodeConstants.SYS_WORKSPACE; - String path = cn + '/' + workspace; - if (dataSessionsInUse.contains(path)) { - try { - wait(1000); - if (dataSessionsInUse.contains(path)) { - Session session = login(repository, workspace); - additionalDataSessions.add(session); - if (log.isTraceEnabled()) - log.trace("Additional data session " + path + " for " + userDn); - return session; - } - } catch (InterruptedException e) { - // silent - } - } - - Session session = null; - if (dataSessions.containsKey(path)) { - session = dataSessions.get(path); - } else { - session = login(repository, workspace); - dataSessions.put(path, session); - if (log.isTraceEnabled()) - log.trace("New data session " + path + " for " + userDn); - } - dataSessionsInUse.add(path); - return session; - } - - private Session login(Repository repository, String workspace) { - try { - return Subject.doAs(getSubject(), new PrivilegedExceptionAction() { - @Override - public Session run() throws Exception { - return repository.login(workspace); - } - }); - } catch (PrivilegedActionException e) { - throw new IllegalStateException("Cannot log in " + userDn + " to JCR", e); - } - } - - public synchronized void releaseDataSession(String cn, Session session) { - if (additionalDataSessions.contains(session)) { - JcrUtils.logoutQuietly(session); - additionalDataSessions.remove(session); - if (log.isTraceEnabled()) - log.trace("Remove additional data session " + session); - return; - } - String path = cn + '/' + session.getWorkspace().getName(); - if (!dataSessionsInUse.contains(path)) - log.warn("Data session " + path + " was not in use for " + userDn); - dataSessionsInUse.remove(path); - Session registeredSession = dataSessions.get(path); - if (session != registeredSession) - log.warn("Data session " + path + " not consistent for " + userDn); - if (log.isTraceEnabled()) - log.trace("Released data session " + session + " for " + path); - notifyAll(); - } - @Override public boolean isValid() { return !isClosed(); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsUserManagerImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsUserManagerImpl.java index e64a6ad93..d21e8616c 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsUserManagerImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsUserManagerImpl.java @@ -19,7 +19,6 @@ import java.util.Map; import java.util.Set; import java.util.UUID; -import javax.jcr.Node; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; import javax.security.auth.Subject; @@ -32,7 +31,6 @@ import org.argeo.api.NodeConstants; import org.argeo.cms.CmsUserManager; import org.argeo.cms.auth.CurrentUser; import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.jcr.JcrUtils; import org.argeo.naming.LdapAttrs; import org.argeo.naming.NamingUtils; import org.argeo.naming.SharedSecret; @@ -435,36 +433,36 @@ public class CmsUserManagerImpl implements CmsUserManager { } } - public User createUserFromPerson(Node person) { - String email = JcrUtils.get(person, LdapAttrs.mail.property()); - String dn = buildDefaultDN(email, Role.USER); - User user; - try { - userTransaction.begin(); - user = (User) userAdmin.createRole(dn, Role.USER); - Dictionary userProperties = user.getProperties(); - String name = JcrUtils.get(person, LdapAttrs.displayName.property()); - userProperties.put(LdapAttrs.cn.name(), name); - userProperties.put(LdapAttrs.displayName.name(), name); - String givenName = JcrUtils.get(person, LdapAttrs.givenName.property()); - String surname = JcrUtils.get(person, LdapAttrs.sn.property()); - userProperties.put(LdapAttrs.givenName.name(), givenName); - userProperties.put(LdapAttrs.sn.name(), surname); - userProperties.put(LdapAttrs.mail.name(), email.toLowerCase()); - userTransaction.commit(); - } catch (Exception e) { - try { - userTransaction.rollback(); - } catch (Exception e1) { - log.error("Could not roll back", e1); - } - if (e instanceof RuntimeException) - throw (RuntimeException) e; - else - throw new RuntimeException("Cannot create user", e); - } - return user; - } +// public User createUserFromPerson(Node person) { +// String email = JcrUtils.get(person, LdapAttrs.mail.property()); +// String dn = buildDefaultDN(email, Role.USER); +// User user; +// try { +// userTransaction.begin(); +// user = (User) userAdmin.createRole(dn, Role.USER); +// Dictionary userProperties = user.getProperties(); +// String name = JcrUtils.get(person, LdapAttrs.displayName.property()); +// userProperties.put(LdapAttrs.cn.name(), name); +// userProperties.put(LdapAttrs.displayName.name(), name); +// String givenName = JcrUtils.get(person, LdapAttrs.givenName.property()); +// String surname = JcrUtils.get(person, LdapAttrs.sn.property()); +// userProperties.put(LdapAttrs.givenName.name(), givenName); +// userProperties.put(LdapAttrs.sn.name(), surname); +// userProperties.put(LdapAttrs.mail.name(), email.toLowerCase()); +// userTransaction.commit(); +// } catch (Exception e) { +// try { +// userTransaction.rollback(); +// } catch (Exception e1) { +// log.error("Could not roll back", e1); +// } +// if (e instanceof RuntimeException) +// throw (RuntimeException) e; +// else +// throw new RuntimeException("Cannot create user", e); +// } +// return user; +// } public UserAdmin getUserAdmin() { return userAdmin; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/CmsSessionProvider.java b/org.argeo.cms/src/org/argeo/cms/internal/http/CmsSessionProvider.java index f21f72441..5dd98d2c7 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/CmsSessionProvider.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/CmsSessionProvider.java @@ -1,17 +1,26 @@ package org.argeo.cms.internal.http; import java.io.Serializable; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; +import javax.security.auth.Subject; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.jackrabbit.server.SessionProvider; +import org.argeo.api.NodeConstants; +import org.argeo.cms.auth.CmsSession; import org.argeo.cms.internal.auth.CmsSessionImpl; import org.argeo.jcr.JcrUtils; @@ -26,7 +35,7 @@ public class CmsSessionProvider implements SessionProvider, Serializable { private final String alias; - private LinkedHashMap cmsSessions = new LinkedHashMap<>(); + private LinkedHashMap cmsSessions = new LinkedHashMap<>(); public CmsSessionProvider(String alias) { this.alias = alias; @@ -45,19 +54,121 @@ public class CmsSessionProvider implements SessionProvider, Serializable { } if (cmsSession == null) throw new IllegalStateException("Cannot find a session for request " + request.getRequestURI()); - Session session = cmsSession.getDataSession(alias, workspace, rep); - cmsSessions.put(session, cmsSession); + CmsDataSession cmsDataSession = new CmsDataSession(cmsSession); + Session session = cmsDataSession.getDataSession(alias, workspace, rep); + cmsSessions.put(session, cmsDataSession); return session; } public void releaseSession(Session session) { // JcrUtils.logoutQuietly(session); if (cmsSessions.containsKey(session)) { - CmsSessionImpl cmsSession = cmsSessions.get(session); - cmsSession.releaseDataSession(alias, session); + CmsDataSession cmsDataSession = cmsSessions.get(session); + cmsDataSession.releaseDataSession(alias, session); } else { log.warn("JCR session " + session + " not found in CMS session list. Logging it out..."); JcrUtils.logoutQuietly(session); } } + + static class CmsDataSession { + private CmsSession cmsSession; + + private Map dataSessions = new HashMap<>(); + private Set dataSessionsInUse = new HashSet<>(); + private Set additionalDataSessions = new HashSet<>(); + + private CmsDataSession(CmsSession cmsSession) { + this.cmsSession = cmsSession; + } + + public Session newDataSession(String cn, String workspace, Repository repository) { + checkValid(); + return login(repository, workspace); + } + + public synchronized Session getDataSession(String cn, String workspace, Repository repository) { + checkValid(); + // FIXME make it more robust + if (workspace == null) + workspace = NodeConstants.SYS_WORKSPACE; + String path = cn + '/' + workspace; + if (dataSessionsInUse.contains(path)) { + try { + wait(1000); + if (dataSessionsInUse.contains(path)) { + Session session = login(repository, workspace); + additionalDataSessions.add(session); + if (log.isTraceEnabled()) + log.trace("Additional data session " + path + " for " + cmsSession.getUserDn()); + return session; + } + } catch (InterruptedException e) { + // silent + } + } + + Session session = null; + if (dataSessions.containsKey(path)) { + session = dataSessions.get(path); + } else { + session = login(repository, workspace); + dataSessions.put(path, session); + if (log.isTraceEnabled()) + log.trace("New data session " + path + " for " + cmsSession.getUserDn()); + } + dataSessionsInUse.add(path); + return session; + } + + private Session login(Repository repository, String workspace) { + try { + return Subject.doAs(cmsSession.getSubject(), new PrivilegedExceptionAction() { + @Override + public Session run() throws Exception { + return repository.login(workspace); + } + }); + } catch (PrivilegedActionException e) { + throw new IllegalStateException("Cannot log in " + cmsSession.getUserDn() + " to JCR", e); + } + } + + public synchronized void releaseDataSession(String cn, Session session) { + if (additionalDataSessions.contains(session)) { + JcrUtils.logoutQuietly(session); + additionalDataSessions.remove(session); + if (log.isTraceEnabled()) + log.trace("Remove additional data session " + session); + return; + } + String path = cn + '/' + session.getWorkspace().getName(); + if (!dataSessionsInUse.contains(path)) + log.warn("Data session " + path + " was not in use for " + cmsSession.getUserDn()); + dataSessionsInUse.remove(path); + Session registeredSession = dataSessions.get(path); + if (session != registeredSession) + log.warn("Data session " + path + " not consistent for " + cmsSession.getUserDn()); + if (log.isTraceEnabled()) + log.trace("Released data session " + session + " for " + path); + notifyAll(); + } + + private void checkValid() { + if (!cmsSession.isValid()) + throw new IllegalStateException( + "CMS session " + cmsSession.getUuid() + " is not valid since " + cmsSession.getEnd()); + } + + private void close() { + // FIXME class this when CMS session is closed + synchronized (this) { + // TODO check data session in use ? + for (String path : dataSessions.keySet()) + JcrUtils.logoutQuietly(dataSessions.get(path)); + for (Session session : additionalDataSessions) + JcrUtils.logoutQuietly(session); + } + } + } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/DataHttpContext.java b/org.argeo.cms/src/org/argeo/cms/internal/http/DataHttpContext.java deleted file mode 100644 index edc6326d7..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/DataHttpContext.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.argeo.cms.internal.http; - -import java.io.IOException; -import java.net.URL; - -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; -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.api.NodeConstants; -import org.argeo.cms.auth.HttpRequestCallbackHandler; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.service.http.HttpContext; - -@Deprecated -public class DataHttpContext implements HttpContext { - private final static Log log = LogFactory.getLog(DataHttpContext.class); - - private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); - - // FIXME Make it more unique - private final String httpAuthRealm; - private final boolean forceBasic; - - public DataHttpContext(String httpAuthrealm, boolean forceBasic) { - this.httpAuthRealm = httpAuthrealm; - this.forceBasic = forceBasic; - } - - public DataHttpContext(String httpAuthrealm) { - this(httpAuthrealm, false); - } - - @Override - public boolean handleSecurity(final HttpServletRequest request, HttpServletResponse response) throws IOException { - - if (log.isTraceEnabled()) - HttpUtils.logRequestHeaders(log, request); - LoginContext lc; - try { - lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request, response)); - lc.login(); - } catch (LoginException e) { - lc = processUnauthorized(request, response); - if (lc == null) - return false; - } - return true; - } - - @Override - public URL getResource(String name) { - return bc.getBundle().getResource(name); - } - - @Override - public String getMimeType(String name) { - return null; - } - - protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) { - // anonymous - try { - LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS, new HttpRequestCallbackHandler(request, response)); - lc.login(); - return lc; - } catch (LoginException e1) { - if (log.isDebugEnabled()) - log.error("Cannot log in as anonymous", e1); - return null; - } - } - protected void askForWwwAuth(HttpServletRequest request, HttpServletResponse response) { - response.setStatus(401); - // response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic - // realm=\"" + httpAuthRealm + "\""); - if (org.argeo.cms.internal.kernel.Activator.getAcceptorCredentials() != null && !forceBasic)// SPNEGO - response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "Negotiate"); - else - response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "Basic realm=\"" + httpAuthRealm + "\""); - - // response.setDateHeader("Date", System.currentTimeMillis()); - // response.setDateHeader("Expires", System.currentTimeMillis() + (24 * - // 60 * 60 * 1000)); - // response.setHeader("Accept-Ranges", "bytes"); - // response.setHeader("Connection", "Keep-Alive"); - // response.setHeader("Keep-Alive", "timeout=5, max=97"); - // response.setContentType("text/html; charset=UTF-8"); - - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/PkgServlet.java b/org.argeo.cms/src/org/argeo/cms/internal/http/PkgServlet.java index 9cbd21c9f..e12456ebb 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/PkgServlet.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/PkgServlet.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Collection; -import java.util.Enumeration; import java.util.SortedMap; import java.util.TreeMap; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/PrivateHttpContext.java b/org.argeo.cms/src/org/argeo/cms/internal/http/PrivateHttpContext.java deleted file mode 100644 index 793478c71..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/PrivateHttpContext.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.argeo.cms.internal.http; - -import javax.security.auth.login.LoginContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** Requests authorisation */ -@Deprecated -public class PrivateHttpContext extends DataHttpContext { - - public PrivateHttpContext(String httpAuthrealm, boolean forceBasic) { - super(httpAuthrealm, forceBasic); - } - - public PrivateHttpContext(String httpAuthrealm) { - super(httpAuthrealm); - } - - @Override - protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) { - askForWwwAuth(request, response); - return null; - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/WebCmsSessionImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/http/WebCmsSessionImpl.java index 20f4c032e..ce8190518 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/WebCmsSessionImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/WebCmsSessionImpl.java @@ -11,9 +11,7 @@ import org.osgi.service.useradmin.Authorization; /** CMS session implementation in a web context. */ public class WebCmsSessionImpl extends CmsSessionImpl { - // private final static Log log = - // LogFactory.getLog(WebCmsSessionImpl.class); - + private static final long serialVersionUID = -5178883380637048025L; private HttpSession httpSession; public WebCmsSessionImpl(Subject initialSubject, Authorization authorization, Locale locale, diff --git a/org.argeo.cms/src/org/argeo/cms/internal/jcr/JcrInitUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/jcr/JcrInitUtils.java new file mode 100644 index 000000000..27f011b13 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/jcr/JcrInitUtils.java @@ -0,0 +1,124 @@ +package org.argeo.cms.internal.jcr; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.api.NodeConstants; +import org.argeo.api.NodeDeployment; +import org.argeo.jackrabbit.client.ClientDavexRepositoryFactory; +import org.argeo.jcr.JcrException; +import org.argeo.naming.LdapAttrs; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; + +/** JCR specific init utilities. */ +public class JcrInitUtils { + private final static Log log = LogFactory.getLog(JcrInitUtils.class); + private final static BundleContext bundleContext = FrameworkUtil.getBundle(JcrInitUtils.class).getBundleContext(); + + public static void addToDeployment(NodeDeployment nodeDeployment) { + // node repository +// Dictionary provided = null; + Dictionary provided = nodeDeployment.getProps(NodeConstants.NODE_REPOS_FACTORY_PID, + NodeConstants.NODE); + Dictionary nodeConfig = JcrInitUtils.getNodeRepositoryConfig(provided); + // node repository is mandatory + nodeDeployment.addFactoryDeployConfig(NodeConstants.NODE_REPOS_FACTORY_PID, nodeConfig); + + // additional repositories +// dataModels: for (DataModels.DataModel dataModel : dataModels.getNonAbstractDataModels()) { +// if (NodeConstants.NODE_REPOSITORY.equals(dataModel.getName())) +// continue dataModels; +// Dictionary config = JcrInitUtils.getRepositoryConfig(dataModel.getName(), +// getProps(NodeConstants.NODE_REPOS_FACTORY_PID, dataModel.getName())); +// if (config.size() != 0) +// putFactoryDeployConfig(NodeConstants.NODE_REPOS_FACTORY_PID, config); +// } + + } + + /** Override the provided config with the framework properties */ + public static Dictionary getNodeRepositoryConfig(Dictionary provided) { + Dictionary props = provided != null ? provided : new Hashtable(); + for (RepoConf repoConf : RepoConf.values()) { + Object value = getFrameworkProp(NodeConstants.NODE_REPO_PROP_PREFIX + repoConf.name()); + if (value != null) { + props.put(repoConf.name(), value); + if (log.isDebugEnabled()) + log.debug("Set node repo configuration " + repoConf.name() + " to " + value); + } + } + props.put(NodeConstants.CN, NodeConstants.NODE_REPOSITORY); + return props; + } + + public static Dictionary getRepositoryConfig(String dataModelName, + Dictionary provided) { + if (dataModelName.equals(NodeConstants.NODE_REPOSITORY) || dataModelName.equals(NodeConstants.EGO_REPOSITORY)) + throw new IllegalArgumentException("Data model '" + dataModelName + "' is reserved."); + Dictionary props = provided != null ? provided : new Hashtable(); + for (RepoConf repoConf : RepoConf.values()) { + Object value = getFrameworkProp( + NodeConstants.NODE_REPOS_PROP_PREFIX + dataModelName + '.' + repoConf.name()); + if (value != null) { + props.put(repoConf.name(), value); + if (log.isDebugEnabled()) + log.debug("Set " + dataModelName + " repo configuration " + repoConf.name() + " to " + value); + } + } + if (props.size() != 0) + props.put(NodeConstants.CN, dataModelName); + return props; + } + + private static void registerRemoteInit(String uri) { + try { + Repository repository = createRemoteRepository(new URI(uri)); + Hashtable properties = new Hashtable<>(); + properties.put(NodeConstants.CN, NodeConstants.NODE_INIT); + properties.put(LdapAttrs.labeledURI.name(), uri); + properties.put(Constants.SERVICE_RANKING, -1000); + bundleContext.registerService(Repository.class, repository, properties); + } catch (RepositoryException e) { + throw new JcrException(e); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + private static Repository createRemoteRepository(URI uri) throws RepositoryException { + RepositoryFactory repositoryFactory = new ClientDavexRepositoryFactory(); + Map params = new HashMap(); + params.put(ClientDavexRepositoryFactory.JACKRABBIT_DAVEX_URI, uri.toString()); + // TODO make it configurable + params.put(ClientDavexRepositoryFactory.JACKRABBIT_REMOTE_DEFAULT_WORKSPACE, NodeConstants.SYS_WORKSPACE); + return repositoryFactory.getRepository(params); + } + + private static String getFrameworkProp(String key, String def) { + String value; + if (bundleContext != null) + value = bundleContext.getProperty(key); + else + value = System.getProperty(key); + if (value == null) + return def; + return value; + } + + private static String getFrameworkProp(String key) { + return getFrameworkProp(key, null); + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java index 2667d986a..026f9186b 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java @@ -15,6 +15,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Dictionary; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; @@ -45,6 +46,7 @@ import org.argeo.cms.ArgeoNames; import org.argeo.cms.internal.http.CmsRemotingServlet; import org.argeo.cms.internal.http.CmsWebDavServlet; import org.argeo.cms.internal.http.HttpUtils; +import org.argeo.cms.internal.jcr.JcrInitUtils; import org.argeo.jcr.Jcr; import org.argeo.jcr.JcrException; import org.argeo.jcr.JcrUtils; @@ -155,6 +157,7 @@ public class CmsDeployment implements NodeDeployment { throw new IllegalStateException("Cannot analyse clean state", e); } deployConfig = new DeployConfig(configurationAdmin, dataModels, isClean); + JcrInitUtils.addToDeployment(CmsDeployment.this); httpExpected = deployConfig.getProps(KernelConstants.JETTY_FACTORY_PID, "default") != null; try { Configuration[] configs = configurationAdmin @@ -181,6 +184,20 @@ public class CmsDeployment implements NodeDeployment { KernelUtils.asyncOpen(confAdminSt); } + public void addFactoryDeployConfig(String factoryPid, Dictionary props) { + deployConfig.putFactoryDeployConfig(factoryPid, props); + deployConfig.save(); + try { + deployConfig.loadConfigs(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public Dictionary getProps(String factoryPid, String cn) { + return deployConfig.getProps(factoryPid, cn); + } + private String httpPortsMsg(Object httpPort, Object httpsPort) { return (httpPort != null ? "HTTP " + httpPort + " " : " ") + (httpsPort != null ? "HTTPS " + httpsPort : ""); } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsWorkspace.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsWorkspace.java deleted file mode 100644 index 2033241f7..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsWorkspace.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.argeo.cms.internal.kernel; - -import java.io.IOException; -import java.io.InputStream; - -import javax.jcr.AccessDeniedException; -import javax.jcr.InvalidItemStateException; -import javax.jcr.InvalidSerializedDataException; -import javax.jcr.ItemExistsException; -import javax.jcr.NamespaceRegistry; -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.PathNotFoundException; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.UnsupportedRepositoryOperationException; -import javax.jcr.Workspace; -import javax.jcr.lock.LockException; -import javax.jcr.lock.LockManager; -import javax.jcr.nodetype.ConstraintViolationException; -import javax.jcr.nodetype.NodeTypeManager; -import javax.jcr.observation.ObservationManager; -import javax.jcr.query.QueryManager; -import javax.jcr.version.Version; -import javax.jcr.version.VersionException; -import javax.jcr.version.VersionManager; - -import org.xml.sax.ContentHandler; - -public class CmsWorkspace implements Workspace { - private String name; - private Session session; - - @Override - public Session getSession() { - return session; - } - - @Override - public String getName() { - return name; - } - - @Override - public void copy(String srcAbsPath, String destAbsPath) throws ConstraintViolationException, VersionException, - AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public void copy(String srcWorkspace, String srcAbsPath, String destAbsPath) - throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, - PathNotFoundException, ItemExistsException, LockException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public void clone(String srcWorkspace, String srcAbsPath, String destAbsPath, boolean removeExisting) - throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, - PathNotFoundException, ItemExistsException, LockException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public void move(String srcAbsPath, String destAbsPath) throws ConstraintViolationException, VersionException, - AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public void restore(Version[] versions, boolean removeExisting) - throws ItemExistsException, UnsupportedRepositoryOperationException, VersionException, LockException, - InvalidItemStateException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public LockManager getLockManager() throws UnsupportedRepositoryOperationException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public QueryManager getQueryManager() throws RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public NamespaceRegistry getNamespaceRegistry() throws RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public NodeTypeManager getNodeTypeManager() throws RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public ObservationManager getObservationManager() - throws UnsupportedRepositoryOperationException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public VersionManager getVersionManager() throws UnsupportedRepositoryOperationException, RepositoryException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String[] getAccessibleWorkspaceNames() throws RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior) throws PathNotFoundException, - ConstraintViolationException, VersionException, LockException, AccessDeniedException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) throws IOException, VersionException, - PathNotFoundException, ItemExistsException, ConstraintViolationException, InvalidSerializedDataException, - LockException, AccessDeniedException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public void createWorkspace(String name) - throws AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public void createWorkspace(String name, String srcWorkspace) throws AccessDeniedException, - UnsupportedRepositoryOperationException, NoSuchWorkspaceException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public void deleteWorkspace(String name) throws AccessDeniedException, UnsupportedRepositoryOperationException, - NoSuchWorkspaceException, RepositoryException { - throw new UnsupportedOperationException(); - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java index f481f3fa1..036aa93d2 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java @@ -45,6 +45,8 @@ class DeployConfig implements ConfigurationListener { private boolean isFirstInit = false; private final static String ROLES = "roles"; + + private ConfigurationAdmin configurationAdmin; public DeployConfig(ConfigurationAdmin configurationAdmin, DataModels dataModels, boolean isClean) { this.dataModels = dataModels; @@ -55,6 +57,7 @@ class DeployConfig implements ConfigurationListener { isFirstInit = true; firstInit(); } + this.configurationAdmin = configurationAdmin; init(configurationAdmin, isClean, isFirstInit); } catch (IOException e) { throw new RuntimeException("Could not init deploy configs", e); @@ -80,21 +83,6 @@ class DeployConfig implements ConfigurationListener { } private void setFromFrameworkProperties(boolean isFirstInit) { - // node repository - Dictionary nodeConfig = InitUtils - .getNodeRepositoryConfig(getProps(NodeConstants.NODE_REPOS_FACTORY_PID, NodeConstants.NODE)); - // node repository is mandatory - putFactoryDeployConfig(NodeConstants.NODE_REPOS_FACTORY_PID, nodeConfig); - - // additional repositories - dataModels: for (DataModels.DataModel dataModel : dataModels.getNonAbstractDataModels()) { - if (NodeConstants.NODE_REPOSITORY.equals(dataModel.getName())) - continue dataModels; - Dictionary config = InitUtils.getRepositoryConfig(dataModel.getName(), - getProps(NodeConstants.NODE_REPOS_FACTORY_PID, dataModel.getName())); - if (config.size() != 0) - putFactoryDeployConfig(NodeConstants.NODE_REPOS_FACTORY_PID, config); - } // user admin List> userDirectoryConfigs = InitUtils.getUserDirectoryConfigs(); @@ -197,54 +185,58 @@ class DeployConfig implements ConfigurationListener { if (log.isDebugEnabled()) log.debug("Clean state, loading from framework properties..."); setFromFrameworkProperties(isFirstInit); - + loadConfigs(); + } + // TODO check consistency if not clean + } + + public void loadConfigs() throws IOException { + // FIXME make it more robust + Configuration systemRolesConf = null; + LdapName systemRolesDn; + try { // FIXME make it more robust - Configuration systemRolesConf = null; - LdapName systemRolesDn; - try { - // FIXME make it more robust - systemRolesDn = new LdapName("cn=roles,ou=org.argeo.api.userAdmin,ou=deploy,ou=node"); - } catch (InvalidNameException e) { - throw new IllegalArgumentException(e); - } - deployConfigs: for (LdapName dn : deployConfigs.keySet()) { - Rdn lastRdn = dn.getRdn(dn.size() - 1); - LdapName prefix = (LdapName) dn.getPrefix(dn.size() - 1); - if (prefix.toString().equals(NodeConstants.DEPLOY_BASEDN)) { - if (lastRdn.getType().equals(NodeConstants.CN)) { - // service - String pid = lastRdn.getValue().toString(); - Configuration conf = configurationAdmin.getConfiguration(pid); - AttributesDictionary dico = new AttributesDictionary(deployConfigs.get(dn)); - conf.update(dico); - } else { - // service factory definition - } + systemRolesDn = new LdapName("cn=roles,ou=org.argeo.api.userAdmin,ou=deploy,ou=node"); + } catch (InvalidNameException e) { + throw new IllegalArgumentException(e); + } + deployConfigs: for (LdapName dn : deployConfigs.keySet()) { + Rdn lastRdn = dn.getRdn(dn.size() - 1); + LdapName prefix = (LdapName) dn.getPrefix(dn.size() - 1); + if (prefix.toString().equals(NodeConstants.DEPLOY_BASEDN)) { + if (lastRdn.getType().equals(NodeConstants.CN)) { + // service + String pid = lastRdn.getValue().toString(); + Configuration conf = configurationAdmin.getConfiguration(pid); + AttributesDictionary dico = new AttributesDictionary(deployConfigs.get(dn)); + conf.update(dico); } else { - Attributes config = deployConfigs.get(dn); - Attribute disabled = config.get(UserAdminConf.disabled.name()); - if (disabled != null) - continue deployConfigs; - // service factory service - Rdn beforeLastRdn = dn.getRdn(dn.size() - 2); - assert beforeLastRdn.getType().equals(NodeConstants.OU); - String factoryPid = beforeLastRdn.getValue().toString(); - Configuration conf = configurationAdmin.createFactoryConfiguration(factoryPid.toString(), null); - if (systemRolesDn.equals(dn)) { - systemRolesConf = configurationAdmin.createFactoryConfiguration(factoryPid.toString(), null); - } else { - AttributesDictionary dico = new AttributesDictionary(config); - conf.update(dico); - } + // service factory definition + } + } else { + Attributes config = deployConfigs.get(dn); + Attribute disabled = config.get(UserAdminConf.disabled.name()); + if (disabled != null) + continue deployConfigs; + // service factory service + Rdn beforeLastRdn = dn.getRdn(dn.size() - 2); + assert beforeLastRdn.getType().equals(NodeConstants.OU); + String factoryPid = beforeLastRdn.getValue().toString(); + Configuration conf = configurationAdmin.createFactoryConfiguration(factoryPid.toString(), null); + if (systemRolesDn.equals(dn)) { + systemRolesConf = configurationAdmin.createFactoryConfiguration(factoryPid.toString(), null); + } else { + AttributesDictionary dico = new AttributesDictionary(config); + conf.update(dico); } } - - // system roles must be last since it triggers node user admin publication - if (systemRolesConf == null) - throw new IllegalStateException("System roles are not configured."); - systemRolesConf.update(new AttributesDictionary(deployConfigs.get(systemRolesDn))); } - // TODO check consistency if not clean + + // system roles must be last since it triggers node user admin publication + if (systemRolesConf == null) + throw new IllegalStateException("System roles are not configured."); + systemRolesConf.update(new AttributesDictionary(deployConfigs.get(systemRolesDn))); + } @Override @@ -366,7 +358,7 @@ class DeployConfig implements ConfigurationListener { } } - Dictionary getProps(String factoryPid, String cn) { +public Dictionary getProps(String factoryPid, String cn) { Attributes attrs = deployConfigs.get(serviceDn(factoryPid, cn)); if (attrs != null) return new AttributesDictionary(attrs); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/InitUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/InitUtils.java index 95d17d8a2..3c40a389b 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/InitUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/InitUtils.java @@ -46,38 +46,6 @@ import org.osgi.framework.Constants; class InitUtils { private final static Log log = LogFactory.getLog(InitUtils.class); - /** Override the provided config with the framework properties */ - static Dictionary getNodeRepositoryConfig(Dictionary provided) { - Dictionary props = provided != null ? provided : new Hashtable(); - for (RepoConf repoConf : RepoConf.values()) { - Object value = getFrameworkProp(NodeConstants.NODE_REPO_PROP_PREFIX + repoConf.name()); - if (value != null) { - props.put(repoConf.name(), value); - if (log.isDebugEnabled()) - log.debug("Set node repo configuration " + repoConf.name() + " to " + value); - } - } - props.put(NodeConstants.CN, NodeConstants.NODE_REPOSITORY); - return props; - } - - static Dictionary getRepositoryConfig(String dataModelName, Dictionary provided) { - if (dataModelName.equals(NodeConstants.NODE_REPOSITORY) || dataModelName.equals(NodeConstants.EGO_REPOSITORY)) - throw new IllegalArgumentException("Data model '" + dataModelName + "' is reserved."); - Dictionary props = provided != null ? provided : new Hashtable(); - for (RepoConf repoConf : RepoConf.values()) { - Object value = getFrameworkProp( - NodeConstants.NODE_REPOS_PROP_PREFIX + dataModelName + '.' + repoConf.name()); - if (value != null) { - props.put(repoConf.name(), value); - if (log.isDebugEnabled()) - log.debug("Set " + dataModelName + " repo configuration " + repoConf.name() + " to " + value); - } - } - if (props.size() != 0) - props.put(NodeConstants.CN, dataModelName); - return props; - } /** Override the provided config with the framework properties */ static Dictionary getHttpServerConfig(Dictionary provided) { @@ -271,7 +239,8 @@ class InitUtils { for (String nodeInit : nodeInits.split(",")) { if (nodeInit.startsWith("http")) { - registerRemoteInit(nodeInit); + // TODO reconnect it + //registerRemoteInit(nodeInit); } else { // TODO use java.nio.file @@ -300,31 +269,6 @@ class InitUtils { } } - private static void registerRemoteInit(String uri) { - try { - BundleContext bundleContext = KernelUtils.getBundleContext(); - Repository repository = createRemoteRepository(new URI(uri)); - Hashtable properties = new Hashtable<>(); - properties.put(NodeConstants.CN, NodeConstants.NODE_INIT); - properties.put(LdapAttrs.labeledURI.name(), uri); - properties.put(Constants.SERVICE_RANKING, -1000); - bundleContext.registerService(Repository.class, repository, properties); - } catch (RepositoryException e) { - throw new JcrException(e); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - } - - private static Repository createRemoteRepository(URI uri) throws RepositoryException { - RepositoryFactory repositoryFactory = new ClientDavexRepositoryFactory(); - Map params = new HashMap(); - params.put(ClientDavexRepositoryFactory.JACKRABBIT_DAVEX_URI, uri.toString()); - // TODO make it configurable - params.put(ClientDavexRepositoryFactory.JACKRABBIT_REMOTE_DEFAULT_WORKSPACE, NodeConstants.SYS_WORKSPACE); - return repositoryFactory.getRepository(params); - } - private static void createSelfSignedKeyStore(Path keyStorePath, char[] keyStorePassword, String keyStoreType) { // for (Provider provider : Security.getProviders()) // System.out.println(provider.getName()); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java index a127866e3..a0f9c5b71 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java @@ -1,6 +1,5 @@ package org.argeo.cms.internal.kernel; -import java.awt.image.Kernel; import java.io.File; import java.lang.management.ManagementFactory; @@ -11,7 +10,7 @@ import org.apache.jackrabbit.stats.RepositoryStatisticsImpl; import org.argeo.cms.internal.auth.CmsSessionImpl; /** - * Background thread started by the {@link Kernel}, which gather statistics and + * Background thread started by the kernel, which gather statistics and * monitor/control other processes. */ class KernelThread extends Thread { diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeAuthorization.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeAuthorization.java deleted file mode 100644 index ddb9730e6..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeAuthorization.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.argeo.cms.internal.kernel; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import javax.security.auth.x500.X500Principal; - -import org.osgi.service.useradmin.Authorization; - -@Deprecated -class NodeAuthorization implements Authorization { - private final String name; - private final String displayName; - private final List systemRoles; - private final List roles; - - public NodeAuthorization(String name, String displayName, - Collection systemRoles, String[] roles) { - this.name = new X500Principal(name).getName(); - this.displayName = displayName; - this.systemRoles = Collections.unmodifiableList(new ArrayList( - systemRoles)); - this.roles = Collections.unmodifiableList(Arrays.asList(roles)); - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean hasRole(String name) { - if (systemRoles.contains(name)) - return true; - if (roles.contains(name)) - return true; - return false; - } - - @Override - public String[] getRoles() { - int size = systemRoles.size() + roles.size(); - List res = new ArrayList(size); - res.addAll(systemRoles); - res.addAll(roles); - return res.toArray(new String[size]); - } - - @Override - public int hashCode() { - if (name == null) - return super.hashCode(); - return name.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Authorization)) - return false; - Authorization that = (Authorization) obj; - if (name == null) - return that.getName() == null; - return name.equals(that.getName()); - } - - @Override - public String toString() { - return displayName; - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java deleted file mode 100644 index 353a6c9ce..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java +++ /dev/null @@ -1,314 +0,0 @@ -package org.argeo.cms.internal.kernel; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Properties; - -import javax.jcr.Repository; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.server.SessionProvider; -import org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet; -import org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet; -import org.argeo.api.NodeConstants; -import org.argeo.cms.CmsException; -import org.argeo.cms.internal.http.CmsSessionProvider; -import org.argeo.cms.internal.http.DataHttpContext; -import org.argeo.cms.internal.http.HttpUtils; -import org.argeo.cms.internal.http.LinkServlet; -import org.argeo.cms.internal.http.PrivateHttpContext; -import org.argeo.cms.internal.http.RobotServlet; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.ServiceReference; -import org.osgi.service.http.HttpService; -import org.osgi.service.http.NamespaceException; -import org.osgi.util.tracker.ServiceTracker; - -/** - * Intercepts and enriches http access, mainly focusing on security and - * transactionality. - */ -@Deprecated -public class NodeHttp implements KernelConstants { - private final static Log log = LogFactory.getLog(NodeHttp.class); - - private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); - - private ServiceTracker repositories; - private final ServiceTracker httpServiceTracker; - - private String httpRealm = "Argeo"; - private String webDavConfig = HttpUtils.WEBDAV_CONFIG; -// private final boolean cleanState; - - public NodeHttp() { -// this.cleanState = cleanState; - httpServiceTracker = new PrepareHttpStc(); - // httpServiceTracker.open(); - KernelUtils.asyncOpen(httpServiceTracker); - } - - public void destroy() { - if (repositories != null) - repositories.close(); - } - - public void registerRepositoryServlets(HttpService httpService, String alias, Repository repository) { - if (httpService == null) - throw new CmsException("No HTTP service available"); - try { - registerWebdavServlet(httpService, alias, repository); - registerRemotingServlet(httpService, alias, repository); - if (NodeConstants.EGO_REPOSITORY.equals(alias)) - registerFilesServlet(httpService, alias, repository); - if (log.isTraceEnabled()) - log.trace("Registered servlets for repository '" + alias + "'"); - } catch (Exception e) { - throw new CmsException("Could not register servlets for repository '" + alias + "'", e); - } - } - - public static void unregisterRepositoryServlets(HttpService httpService, String alias) { - if (httpService == null) - return; - try { - httpService.unregister(webdavPath(alias)); - httpService.unregister(remotingPath(alias)); - if (NodeConstants.EGO_REPOSITORY.equals(alias)) - httpService.unregister(filesPath(alias)); - if (log.isTraceEnabled()) - log.trace("Unregistered servlets for repository '" + alias + "'"); - } catch (Exception e) { - log.error("Could not unregister servlets for repository '" + alias + "'", e); - } - } - - void registerWebdavServlet(HttpService httpService, String alias, Repository repository) - throws NamespaceException, ServletException { - // WebdavServlet webdavServlet = new WebdavServlet(repository, new - // OpenInViewSessionProvider(alias)); - WebdavServlet webdavServlet = new WebdavServlet(repository, new CmsSessionProvider(alias)); - String path = webdavPath(alias); - Properties ip = new Properties(); - ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_CONFIG, webDavConfig); - ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path); - httpService.registerServlet(path, webdavServlet, ip, new DataHttpContext(httpRealm)); - } - - void registerFilesServlet(HttpService httpService, String alias, Repository repository) - throws NamespaceException, ServletException { - WebdavServlet filesServlet = new WebdavServlet(repository, new CmsSessionProvider(alias)); - String path = filesPath(alias); - Properties ip = new Properties(); - ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_CONFIG, webDavConfig); - ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path); - httpService.registerServlet(path, filesServlet, ip, new PrivateHttpContext(httpRealm, true)); - } - - void registerRemotingServlet(HttpService httpService, String alias, Repository repository) - throws NamespaceException, ServletException { - RemotingServlet remotingServlet = new RemotingServlet(repository, new CmsSessionProvider(alias)); - String path = remotingPath(alias); - Properties ip = new Properties(); - ip.setProperty(JcrRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path); - ip.setProperty(JcrRemotingServlet.INIT_PARAM_AUTHENTICATE_HEADER, "Negotiate"); - - // Looks like a bug in Jackrabbit remoting init - Path tmpDir; - try { - tmpDir = Files.createTempDirectory("remoting_" + alias); - } catch (IOException e) { - throw new CmsException("Cannot create temp directory for remoting servlet", e); - } - ip.setProperty(RemotingServlet.INIT_PARAM_HOME, tmpDir.toString()); - ip.setProperty(RemotingServlet.INIT_PARAM_TMP_DIRECTORY, "remoting_" + alias); - ip.setProperty(RemotingServlet.INIT_PARAM_PROTECTED_HANDLERS_CONFIG, HttpUtils.DEFAULT_PROTECTED_HANDLERS); - ip.setProperty(RemotingServlet.INIT_PARAM_CREATE_ABSOLUTE_URI, "false"); - httpService.registerServlet(path, remotingServlet, ip, new PrivateHttpContext(httpRealm)); - } - - static String webdavPath(String alias) { - return NodeConstants.PATH_DATA + "/" + alias; - } - - static String remotingPath(String alias) { - return NodeConstants.PATH_JCR + "/" + alias; - } - - static String filesPath(String alias) { - return NodeConstants.PATH_FILES; - } - - class RepositoriesStc extends ServiceTracker { - private final HttpService httpService; - - private final BundleContext bc; - - public RepositoriesStc(BundleContext bc, HttpService httpService) { - super(bc, Repository.class, null); - this.httpService = httpService; - this.bc = bc; - } - - @Override - public Repository addingService(ServiceReference reference) { - Repository repository = bc.getService(reference); - Object jcrRepoAlias = reference.getProperty(NodeConstants.CN); - if (jcrRepoAlias != null) { - String alias = jcrRepoAlias.toString(); - registerRepositoryServlets(httpService, alias, repository); - } - return repository; - } - - @Override - public void modifiedService(ServiceReference reference, Repository service) { - } - - @Override - public void removedService(ServiceReference reference, Repository service) { - Object jcrRepoAlias = reference.getProperty(NodeConstants.CN); - if (jcrRepoAlias != null) { - String alias = jcrRepoAlias.toString(); - unregisterRepositoryServlets(httpService, alias); - } - } - } - - private class PrepareHttpStc extends ServiceTracker { - public PrepareHttpStc() { - super(bc, HttpService.class, null); - } - - @Override - public HttpService addingService(ServiceReference reference) { - long begin = System.currentTimeMillis(); - if (log.isTraceEnabled()) - log.trace("HTTP prepare starts..."); - HttpService httpService = addHttpService(reference); - if (log.isTraceEnabled()) - log.trace("HTTP prepare duration: " + (System.currentTimeMillis() - begin) + "ms"); - return httpService; - } - - @Override - public void removedService(ServiceReference reference, HttpService service) { - repositories.close(); - repositories = null; - } - - private HttpService addHttpService(ServiceReference sr) { - HttpService httpService = bc.getService(sr); - // TODO find constants - Object httpPort = sr.getProperty("http.port"); - Object httpsPort = sr.getProperty("https.port"); - - try { - httpService.registerServlet("/!", new LinkServlet(), null, null); - httpService.registerServlet("/robots.txt", new RobotServlet(), null, null); - // httpService.registerServlet("/html", new HtmlServlet(), null, null); - } catch (Exception e) { - throw new CmsException("Cannot register filters", e); - } - // track repositories - if (repositories != null) - throw new CmsException("An http service is already configured"); - repositories = new RepositoriesStc(bc, httpService); - // repositories.open(); - - ///if (cleanState) - // FIXME properly publish servlets - //KernelUtils.asyncOpen(repositories); - - log.info(httpPortsMsg(httpPort, httpsPort)); - // httpAvailable = true; - // checkReadiness(); - - bc.registerService(NodeHttp.class, NodeHttp.this, null); - return httpService; - } - - private String httpPortsMsg(Object httpPort, Object httpsPort) { - return (httpPort != null ? "HTTP " + httpPort + " " : " ") - + (httpsPort != null ? "HTTPS " + httpsPort : ""); - } - } - - private static class WebdavServlet extends SimpleWebdavServlet { - private static final long serialVersionUID = -4687354117811443881L; - private final Repository repository; - - public WebdavServlet(Repository repository, SessionProvider sessionProvider) { - this.repository = repository; - setSessionProvider(sessionProvider); - } - - public Repository getRepository() { - return repository; - } - - @Override - protected void service(final HttpServletRequest request, final HttpServletResponse response) - throws ServletException, IOException { - WebdavServlet.super.service(request, response); - // try { - // Subject subject = subjectFromRequest(request); - // // TODO make it stronger, with eTags. - // // if (CurrentUser.isAnonymous(subject) && - // // request.getMethod().equals("GET")) { - // // response.setHeader("Cache-Control", "no-transform, public, - // // max-age=300, s-maxage=900"); - // // } - // - // Subject.doAs(subject, new PrivilegedExceptionAction() { - // @Override - // public Void run() throws Exception { - // WebdavServlet.super.service(request, response); - // return null; - // } - // }); - // } catch (PrivilegedActionException e) { - // throw new CmsException("Cannot process webdav request", - // e.getException()); - // } - } - - } - - private static class RemotingServlet extends JcrRemotingServlet { - private final Log log = LogFactory.getLog(RemotingServlet.class); - private static final long serialVersionUID = 4605238259548058883L; - private final Repository repository; - private final SessionProvider sessionProvider; - - public RemotingServlet(Repository repository, SessionProvider sessionProvider) { - this.repository = repository; - this.sessionProvider = sessionProvider; - } - - @Override - protected Repository getRepository() { - return repository; - } - - @Override - protected SessionProvider getSessionProvider() { - return sessionProvider; - } - - @Override - protected void service(final HttpServletRequest request, final HttpServletResponse response) - throws ServletException, IOException { - if (log.isTraceEnabled()) - HttpUtils.logRequest(log, request); - RemotingServlet.super.service(request, response); - } - } - -}