]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java
Move APIs, clean base bundles
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / kernel / NodeUserAdmin.java
index 9dd516137ebe72e268689df709c625132e290e22..d0cf93d80c21e117cf36aae65c869c44981e1a31 100644 (file)
 package org.argeo.cms.internal.kernel;
 
-import java.util.ArrayList;
-import java.util.Arrays;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Dictionary;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
+import java.util.Hashtable;
 import java.util.Map;
-import java.util.Set;
 
-import javax.naming.InvalidNameException;
 import javax.naming.ldap.LdapName;
-import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
-import javax.transaction.TransactionSynchronizationRegistry;
 
-import org.argeo.cms.KernelHeader;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsException;
+import org.argeo.node.NodeConstants;
 import org.argeo.osgi.useradmin.AbstractUserDirectory;
-import org.argeo.osgi.useradmin.UserAdminAggregator;
-import org.argeo.osgi.useradmin.UserDirectoryException;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.useradmin.Authorization;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
+import org.argeo.osgi.useradmin.AggregatingUserAdmin;
+import org.argeo.osgi.useradmin.LdapUserAdmin;
+import org.argeo.osgi.useradmin.LdifUserAdmin;
+import org.argeo.osgi.useradmin.UserAdminConf;
+import org.argeo.osgi.useradmin.UserDirectory;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
 import org.osgi.service.useradmin.UserAdmin;
-
-public class NodeUserAdmin implements UserAdmin, UserAdminAggregator {
-       final static LdapName ROLES_BASE;
-       static {
-               try {
-                       ROLES_BASE = new LdapName(KernelHeader.ROLES_BASEDN);
-               } catch (InvalidNameException e) {
-                       throw new UserDirectoryException("Cannot initialize "
-                                       + NodeUserAdmin.class, e);
-               }
-       }
-
-       private UserAdmin nodeRoles = null;
-       private Map<LdapName, UserAdmin> userAdmins = new HashMap<LdapName, UserAdmin>();
-
-       private TransactionSynchronizationRegistry syncRegistry;
-       private TransactionManager transactionManager;
-
-       @Override
-       public Role createRole(String name, int type) {
-               return findUserAdmin(name).createRole(name, type);
+import org.osgi.util.tracker.ServiceTracker;
+
+import bitronix.tm.BitronixTransactionManager;
+import bitronix.tm.resource.ehcache.EhCacheXAResourceProducer;
+
+/**
+ * Aggregates multiple {@link UserDirectory} and integrates them with system
+ * roles.
+ */
+class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactory, KernelConstants {
+       private final static Log log = LogFactory.getLog(NodeUserAdmin.class);
+       private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
+
+       // OSGi
+       private Map<String, LdapName> pidToBaseDn = new HashMap<>();
+       private Map<String, ServiceRegistration<UserDirectory>> pidToServiceRegs = new HashMap<>();
+       private ServiceRegistration<UserAdmin> userAdminReg;
+
+       // JTA
+       private final ServiceTracker<TransactionManager, TransactionManager> tmTracker;
+       private final String cacheName = UserDirectory.class.getName();
+
+       public NodeUserAdmin(String systemRolesBaseDn) {
+               super(systemRolesBaseDn);
+               tmTracker = new ServiceTracker<>(bc, TransactionManager.class, null);
+               tmTracker.open();
        }
 
        @Override
-       public boolean removeRole(String name) {
-               return findUserAdmin(name).removeRole(name);
-       }
-
-       @Override
-       public Role getRole(String name) {
-               return findUserAdmin(name).getRole(name);
-       }
-
-       @Override
-       public Role[] getRoles(String filter) throws InvalidSyntaxException {
-               List<Role> res = new ArrayList<Role>();
-               for (UserAdmin userAdmin : userAdmins.values()) {
-                       res.addAll(Arrays.asList(userAdmin.getRoles(filter)));
+       public void updated(String pid, Dictionary<String, ?> properties) throws ConfigurationException {
+               String uri = (String) properties.get(UserAdminConf.uri.name());
+               URI u;
+               try {
+                       u = new URI(uri);
+               } catch (URISyntaxException e) {
+                       throw new CmsException("Badly formatted URI " + uri, e);
                }
-               res.addAll(Arrays.asList(nodeRoles.getRoles(filter)));
-               return res.toArray(new Role[res.size()]);
-       }
 
-       @Override
-       public User getUser(String key, String value) {
-               List<User> res = new ArrayList<User>();
-               for (UserAdmin userAdmin : userAdmins.values()) {
-                       User u = userAdmin.getUser(key, value);
-                       if (u != null)
-                               res.add(u);
+               // Create
+               AbstractUserDirectory userDirectory = u.getScheme().equals("ldap") ? new LdapUserAdmin(properties)
+                               : new LdifUserAdmin(properties);
+               addUserDirectory(userDirectory);
+
+               // OSGi
+               LdapName baseDn = userDirectory.getBaseDn();
+               Dictionary<String, Object> regProps = new Hashtable<>();
+               regProps.put(Constants.SERVICE_PID, pid);
+               if(isSystemRolesBaseDn(baseDn))
+                       regProps.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE);
+               regProps.put(UserAdminConf.baseDn.name(), baseDn);
+               ServiceRegistration<UserDirectory> reg = bc.registerService(UserDirectory.class, userDirectory, regProps);
+               pidToBaseDn.put(pid, baseDn);
+               pidToServiceRegs.put(pid, reg);
+
+               if (log.isDebugEnabled())
+                       log.debug("User directory " + userDirectory.getBaseDn() + " [" + u.getScheme() + "] enabled.");
+
+               if (!isSystemRolesBaseDn(baseDn)) {
+                       if (userAdminReg != null)
+                               userAdminReg.unregister();
+                       // register self as main user admin
+                       Dictionary<String, Object> userAdminregProps = currentState();
+                       userAdminregProps.put(NodeConstants.CN, NodeConstants.DEFAULT);
+                       userAdminregProps.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE);
+                       userAdminReg = bc.registerService(UserAdmin.class, this, userAdminregProps);
                }
-               // Note: node roles cannot contain users, so it is not searched
-               return res.size() == 1 ? res.get(0) : null;
        }
 
        @Override
-       public Authorization getAuthorization(User user) {
-               UserAdmin userAdmin = findUserAdmin(user.getName());
-               Authorization rawAuthorization = userAdmin.getAuthorization(user);
-               // gather system roles
-               Set<String> systemRoles = new HashSet<String>();
-               for (String role : rawAuthorization.getRoles()) {
-                       Authorization auth = nodeRoles.getAuthorization((User) userAdmin
-                                       .getRole(role));
-                       systemRoles.addAll(Arrays.asList(auth.getRoles()));
-               }
-               return new NodeAuthorization(rawAuthorization.getName(),
-                               rawAuthorization.toString(), systemRoles,
-                               rawAuthorization.getRoles());
+       public void deleted(String pid) {
+               assert pidToServiceRegs.get(pid) != null;
+               assert pidToBaseDn.get(pid) != null;
+               pidToServiceRegs.remove(pid).unregister();
+               LdapName baseDn = pidToBaseDn.remove(pid);
+               removeUserDirectory(baseDn);
        }
 
-       //
-       // USER ADMIN AGGREGATOR
-       //
        @Override
-       public synchronized void addUserAdmin(String baseDn, UserAdmin userAdmin) {
-               if (userAdmin instanceof AbstractUserDirectory)
-                       ((AbstractUserDirectory) userAdmin).setSyncRegistry(syncRegistry);
-
-               if (baseDn.equals(KernelHeader.ROLES_BASEDN)) {
-                       nodeRoles = userAdmin;
-                       return;
-               }
-
-               if (userAdmins.containsKey(baseDn))
-                       throw new UserDirectoryException(
-                                       "There is already a user admin for " + baseDn);
-               try {
-                       userAdmins.put(new LdapName(baseDn), userAdmin);
-               } catch (InvalidNameException e) {
-                       throw new UserDirectoryException("Badly formatted base DN "
-                                       + baseDn, e);
-               }
-       }
-
-       @Override
-       public synchronized void removeUserAdmin(String baseDn) {
-               if (baseDn.equals(KernelHeader.ROLES_BASEDN))
-                       throw new UserDirectoryException("Node roles cannot be removed.");
-               LdapName base;
-               try {
-                       base = new LdapName(baseDn);
-               } catch (InvalidNameException e) {
-                       throw new UserDirectoryException("Badly formatted base DN "
-                                       + baseDn, e);
-               }
-               if (!userAdmins.containsKey(base))
-                       throw new UserDirectoryException("There is no user admin for "
-                                       + base);
-               UserAdmin userAdmin = userAdmins.remove(base);
-               if (userAdmin instanceof AbstractUserDirectory)
-                       ((AbstractUserDirectory) userAdmin).setSyncRegistry(null);
+       public String getName() {
+               return "Node User Admin";
        }
 
-       private UserAdmin findUserAdmin(String name) {
-               try {
-                       return findUserAdmin(new LdapName(name));
-               } catch (InvalidNameException e) {
-                       throw new UserDirectoryException("Badly formatted name " + name, e);
-               }
-       }
-
-       private UserAdmin findUserAdmin(LdapName name) {
-               if (name.startsWith(ROLES_BASE))
-                       return nodeRoles;
-               List<UserAdmin> res = new ArrayList<UserAdmin>(1);
-               for (LdapName baseDn : userAdmins.keySet()) {
-                       if (name.startsWith(baseDn))
-                               res.add(userAdmins.get(baseDn));
-               }
-               if (res.size() == 0)
-                       throw new UserDirectoryException("Cannot find user admin for "
-                                       + name);
-               if (res.size() > 1)
-                       throw new UserDirectoryException("Multiple user admin found for "
-                                       + name);
-               return res.get(0);
+       protected void postAdd(AbstractUserDirectory userDirectory) {
+               // JTA
+               TransactionManager tm = tmTracker.getService();
+               if (tm == null)
+                       throw new CmsException("A JTA transaction manager must be available.");
+               userDirectory.setTransactionManager(tm);
+               if (tmTracker.getService() instanceof BitronixTransactionManager)
+                       EhCacheXAResourceProducer.registerXAResource(cacheName, userDirectory.getXaResource());
        }
 
-       public void setTransactionManager(TransactionManager transactionManager) {
-               this.transactionManager = transactionManager;
-               if (nodeRoles instanceof AbstractUserDirectory)
-                       ((AbstractUserDirectory) nodeRoles)
-                                       .setTransactionManager(transactionManager);
-               for (UserAdmin userAdmin : userAdmins.values()) {
-                       if (userAdmin instanceof AbstractUserDirectory)
-                               ((AbstractUserDirectory) userAdmin)
-                                               .setTransactionManager(transactionManager);
-               }
-       }
-
-       public void setSyncRegistry(TransactionSynchronizationRegistry syncRegistry) {
-               this.syncRegistry = syncRegistry;
-               if (nodeRoles instanceof AbstractUserDirectory)
-                       ((AbstractUserDirectory) nodeRoles).setSyncRegistry(syncRegistry);
-               for (UserAdmin userAdmin : userAdmins.values()) {
-                       if (userAdmin instanceof AbstractUserDirectory)
-                               ((AbstractUserDirectory) userAdmin)
-                                               .setSyncRegistry(syncRegistry);
-               }
+       protected void preDestroy(UserDirectory userDirectory) {
+               if (tmTracker.getService() instanceof BitronixTransactionManager)
+                       EhCacheXAResourceProducer.unregisterXAResource(cacheName, userDirectory.getXaResource());
        }
 
 }