org.apache.jackrabbit.*;resolution:=optional,\
org.springframework.ldap.*;resolution:=optional,\
org.springframework.security.ldap.*;resolution:=optional,\
+org.springframework.security.provisioning;resolution:=optional,\
org.joda.time.*;resolution:=optional,\
*
/** Public properties of the CMS Kernel */
public interface KernelHeader {
+ final static String SECURITY_PROVIDER = "BC";// Bouncy Castle
+
// LOGIN CONTEXTS
final static String LOGIN_CONTEXT_USER = "USER";
final static String LOGIN_CONTEXT_ANONYMOUS = "ANONYMOUS";
@Override
public boolean login() throws LoginException {
- // TODO check permission at code level
+ // TODO check permission at code level ?
return true;
}
package org.argeo.cms.internal.kernel;
-import java.io.File;
-import java.io.IOException;
import java.lang.management.ManagementFactory;
-import java.net.URL;
-import java.security.KeyStore;
import java.security.PrivilegedAction;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.jcr.Repository;
import javax.jcr.RepositoryFactory;
import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-import javax.security.auth.x500.X500Principal;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import javax.transaction.UserTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jackrabbit.util.TransientFileFactory;
import org.argeo.ArgeoException;
import org.argeo.cms.CmsException;
-import org.argeo.cms.KernelHeader;
+import org.argeo.cms.internal.transaction.SimpleTransactionManager;
import org.argeo.jackrabbit.OsgiJackrabbitRepositoryFactory;
import org.argeo.jcr.ArgeoJcrConstants;
import org.argeo.security.core.InternalAuthentication;
-import org.argeo.security.crypto.PkiUtils;
import org.eclipse.equinox.http.servlet.ExtendedHttpService;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceEvent;
* </ul>
*/
final class Kernel implements ServiceListener {
-
private final static Log log = LogFactory.getLog(Kernel.class);
private final BundleContext bundleContext = Activator.getBundleContext();
+ private final NodeSecurity nodeSecurity;
ThreadGroup threadGroup = new ThreadGroup(Kernel.class.getSimpleName());
JackrabbitNode node;
- OsgiJackrabbitRepositoryFactory repositoryFactory;
- NodeSecurity nodeSecurity;
- NodeHttp nodeHttp;
- private KernelThread kernelThread;
- private final Subject kernelSubject = new Subject();
+ private SimpleTransactionManager transactionManager;
+ private OsgiJackrabbitRepositoryFactory repositoryFactory;
+ private NodeHttp nodeHttp;
+ private KernelThread kernelThread;
public Kernel() {
- URL url = getClass().getClassLoader().getResource(
- KernelConstants.JAAS_CONFIG);
- System.setProperty("java.security.auth.login.config",
- url.toExternalForm());
- createKeyStoreIfNeeded();
-
- CallbackHandler cbHandler = new CallbackHandler() {
-
- @Override
- public void handle(Callback[] callbacks) throws IOException,
- UnsupportedCallbackException {
- // alias
- ((NameCallback) callbacks[1]).setName(KernelHeader.ROLE_KERNEL);
- // store pwd
- ((PasswordCallback) callbacks[2]).setPassword("changeit"
- .toCharArray());
- // key pwd
- ((PasswordCallback) callbacks[3]).setPassword("changeit"
- .toCharArray());
- }
- };
- try {
- LoginContext kernelLc = new LoginContext(
- KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject,
- cbHandler);
- kernelLc.login();
- } catch (LoginException e) {
- throw new CmsException("Cannot log in kernel", e);
- }
+ nodeSecurity = new NodeSecurity(bundleContext);
}
final void init() {
- Subject.doAs(kernelSubject, new PrivilegedAction<Void>() {
+ Subject.doAs(nodeSecurity.getKernelSubject(),
+ new PrivilegedAction<Void>() {
- @Override
- public Void run() {
- doInit();
- return null;
- }
+ @Override
+ public Void run() {
+ doInit();
+ return null;
+ }
- });
+ });
}
private void doInit() {
SecurityContextHolder.getContext().setAuthentication(initAuth);
try {
+ // Transaction
+ transactionManager = new SimpleTransactionManager();
+ bundleContext.registerService(TransactionManager.class,
+ transactionManager, null);
+ bundleContext.registerService(UserTransaction.class,
+ transactionManager, null);
+ bundleContext.registerService(
+ TransactionSynchronizationRegistry.class,
+ transactionManager.getTransactionSynchronizationRegistry(),
+ null);
+
// Jackrabbit node
node = new JackrabbitNode(bundleContext);
repositoryFactory = new OsgiJackrabbitRepositoryFactory();
// Authentication
- nodeSecurity = new NodeSecurity(bundleContext, node);
+ nodeSecurity.getUserAdmin().setSyncRegistry(
+ transactionManager.getTransactionSynchronizationRegistry());
+ nodeSecurity.getUserAdmin().setTransactionManager(
+ transactionManager);
// Equinox dependency
ExtendedHttpService httpService = waitForHttpService();
if (nodeHttp != null)
nodeHttp.destroy();
- if (nodeSecurity != null)
- nodeSecurity.destroy();
+ // if (nodeSecurity != null)
+ // nodeSecurity.destroy();
if (node != null)
node.destroy();
// Clean hanging threads from Jackrabbit
TransientFileFactory.shutdown();
- try {
- LoginContext kernelLc = new LoginContext(
- KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject);
- kernelLc.logout();
- } catch (LoginException e) {
- throw new CmsException("Cannot log in kernel", e);
- }
+ // Clean hanging Gogo shell thread
+ new GogoShellKiller().start();
+ nodeSecurity.destroy();
long duration = System.currentTimeMillis() - begin;
log.info("## ARGEO CMS DOWN in " + (duration / 1000) + "."
+ (duration % 1000) + "s ##");
return httpService;
}
- private void createKeyStoreIfNeeded() {
- char[] ksPwd = "changeit".toCharArray();
- char[] keyPwd = Arrays.copyOf(ksPwd, ksPwd.length);
- File keyStoreFile = KernelUtils.getOsgiConfigurationFile("node.p12");
- if (!keyStoreFile.exists()) {
- try {
- KeyStore keyStore = PkiUtils.getKeyStore(keyStoreFile, ksPwd);
- X509Certificate cert = PkiUtils.generateSelfSignedCertificate(
- keyStore, new X500Principal(KernelHeader.ROLE_KERNEL),
- keyPwd);
- PkiUtils.saveKeyStore(keyStoreFile, ksPwd, keyStore);
-
- } catch (Exception e) {
- throw new CmsException("Cannot create key store "
- + keyStoreFile, e);
- }
- }
- }
-
final private static void directorsCut(long initDuration) {
// final long ms = 128l + (long) (Math.random() * 128d);
long ms = initDuration / 100;
+ String.format("%.2f", 100 - (sleepAccuracy * 100 - 100))
+ " %");
}
+
+ /** Workaround for blocking Gogo shell by system shutdown. */
+ private class GogoShellKiller extends Thread {
+
+ public GogoShellKiller() {
+ super("Gogo shell killer");
+ setDaemon(true);
+ }
+
+ @Override
+ public void run() {
+ ThreadGroup rootTg = getRootThreadGroup(null);
+ Thread gogoShellThread = findGogoShellThread(rootTg);
+ if (gogoShellThread == null)
+ return;
+ while (getNonDaemonCount(rootTg) > 2) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // silent
+ }
+ }
+ gogoShellThread = findGogoShellThread(rootTg);
+ if (gogoShellThread == null)
+ return;
+ System.exit(0);
+ }
+ }
+
+ private static ThreadGroup getRootThreadGroup(ThreadGroup tg) {
+ if (tg == null)
+ tg = Thread.currentThread().getThreadGroup();
+ if (tg.getParent() == null)
+ return tg;
+ else
+ return getRootThreadGroup(tg.getParent());
+ }
+
+ private static int getNonDaemonCount(ThreadGroup rootThreadGroup) {
+ Thread[] threads = new Thread[rootThreadGroup.activeCount()];
+ rootThreadGroup.enumerate(threads);
+ int nonDameonCount = 0;
+ for (Thread t : threads)
+ if (!t.isDaemon())
+ nonDameonCount++;
+ return nonDameonCount;
+ }
+
+ private static Thread findGogoShellThread(ThreadGroup rootThreadGroup) {
+ Thread[] threads = new Thread[rootThreadGroup.activeCount()];
+ rootThreadGroup.enumerate(threads, true);
+ for (Thread thread : threads) {
+ if (thread.getName().equals("Gogo shell"))
+ return thread;
+ }
+ return null;
+ }
+
}
\ No newline at end of file
import java.io.File;
import java.io.IOException;
+import java.net.URL;
+import java.nio.file.ProviderNotFoundException;
+import java.security.KeyStore;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
-import javax.jcr.RepositoryException;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.x500.X500Principal;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.cms.CmsException;
import org.argeo.cms.KernelHeader;
-import org.argeo.cms.internal.useradmin.SimpleJcrSecurityModel;
-import org.argeo.cms.internal.useradmin.jackrabbit.JackrabbitUserAdminService;
-import org.argeo.osgi.useradmin.AbstractLdapUserAdmin;
+import org.argeo.osgi.useradmin.AbstractUserDirectory;
import org.argeo.osgi.useradmin.LdapUserAdmin;
import org.argeo.osgi.useradmin.LdifUserAdmin;
-import org.argeo.security.OsAuthenticationToken;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.core.InternalAuthentication;
-import org.argeo.security.core.InternalAuthenticationProvider;
-import org.argeo.security.core.OsAuthenticationProvider;
+import org.argeo.security.crypto.PkiUtils;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.UserAdmin;
-import org.springframework.security.authentication.AnonymousAuthenticationProvider;
-import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.provisioning.UserDetailsManager;
/** Authentication and user management. */
class NodeSecurity implements AuthenticationManager {
- private final static Log log = LogFactory.getLog(NodeSecurity.class);
+ private final static Log log;
+ static {
+ log = LogFactory.getLog(NodeSecurity.class);
+ // Make Bouncy Castle the default provider
+ Provider provider = new BouncyCastleProvider();
+ int position = Security.insertProviderAt(provider, 1);
+ if (position == -1)
+ log.error("Provider " + provider.getName()
+ + " already installed and could not be set as default");
+ Provider defaultProvider = Security.getProviders()[0];
+ if (!defaultProvider.getName().equals(KernelHeader.SECURITY_PROVIDER))
+ log.error("Provider name is " + defaultProvider.getName()
+ + " but it should be " + KernelHeader.SECURITY_PROVIDER);
+ }
private final BundleContext bundleContext;
-
- private final OsAuthenticationProvider osAuth;
- private final InternalAuthenticationProvider internalAuth;
- private final AnonymousAuthenticationProvider anonymousAuth;
- private final JackrabbitUserAdminService userAdminService;
private final NodeUserAdmin userAdmin;
+ private final Subject kernelSubject;
+
+ // private final OsAuthenticationProvider osAuth;
+ // private final InternalAuthenticationProvider internalAuth;
+ // private final AnonymousAuthenticationProvider anonymousAuth;
+ // private final JackrabbitUserAdminService userAdminService;
private ServiceRegistration<AuthenticationManager> authenticationManagerReg;
- private ServiceRegistration<UserAdminService> userAdminServiceReg;
- private ServiceRegistration<UserDetailsManager> userDetailsManagerReg;
+ // private ServiceRegistration<UserAdminService> userAdminServiceReg;
+ // private ServiceRegistration<UserDetailsManager> userDetailsManagerReg;
private ServiceRegistration<UserAdmin> userAdminReg;
- public NodeSecurity(BundleContext bundleContext, JackrabbitNode node)
- throws RepositoryException {
+ public NodeSecurity(BundleContext bundleContext) {
+ // Configure JAAS first
+ URL url = getClass().getClassLoader().getResource(
+ KernelConstants.JAAS_CONFIG);
+ System.setProperty("java.security.auth.login.config",
+ url.toExternalForm());
+
this.bundleContext = bundleContext;
+ this.kernelSubject = logKernel();
- osAuth = new OsAuthenticationProvider();
- internalAuth = new InternalAuthenticationProvider(
- Activator.getSystemKey());
- anonymousAuth = new AnonymousAuthenticationProvider(
- Activator.getSystemKey());
+ // osAuth = new OsAuthenticationProvider();
+ // internalAuth = new InternalAuthenticationProvider(
+ // Activator.getSystemKey());
+ // anonymousAuth = new AnonymousAuthenticationProvider(
+ // Activator.getSystemKey());
// user admin
- userAdminService = new JackrabbitUserAdminService();
- userAdminService.setRepository(node);
- userAdminService.setSecurityModel(new SimpleJcrSecurityModel());
- userAdminService.init();
+ // userAdminService = new JackrabbitUserAdminService();
+ // userAdminService.setRepository(node);
+ // userAdminService.setSecurityModel(new SimpleJcrSecurityModel());
+ // userAdminService.init();
userAdmin = new NodeUserAdmin();
- String baseDn = "dc=example,dc=com";
+ File osgiInstanceDir = KernelUtils.getOsgiInstanceDir();
+ File homeDir = new File(osgiInstanceDir, "node");
+ homeDir.mkdirs();
+
String userAdminUri = KernelUtils
.getFrameworkProp(KernelConstants.USERADMIN_URI);
- if (userAdminUri == null)
- userAdminUri = getClass().getResource(baseDn + ".ldif").toString();
+ String baseDn = "dc=example,dc=com";
+ if (userAdminUri == null) {
+ File businessRolesFile = new File(homeDir, baseDn + ".ldif");
+ // userAdminUri = getClass().getResource(baseDn +
+ // ".ldif").toString();
+ if (!businessRolesFile.exists())
+ try {
+ FileUtils.copyInputStreamToFile(getClass()
+ .getResourceAsStream(baseDn + ".ldif"),
+ businessRolesFile);
+ } catch (IOException e) {
+ throw new CmsException("Cannot copy demo resource", e);
+ }
+ userAdminUri = businessRolesFile.toURI().toString();
+ }
- AbstractLdapUserAdmin businessRoles;
+ AbstractUserDirectory businessRoles;
if (userAdminUri.startsWith("ldap"))
businessRoles = new LdapUserAdmin(userAdminUri);
else {
businessRoles.init();
userAdmin.addUserAdmin(baseDn, businessRoles);
- File osgiInstanceDir = KernelUtils.getOsgiInstanceDir();
- File homeDir = new File(osgiInstanceDir, "node");
-
String baseNodeRoleDn = KernelHeader.ROLES_BASEDN;
File nodeRolesFile = new File(homeDir, baseNodeRoleDn + ".ldif");
- try {
- FileUtils.copyInputStreamToFile(
- getClass().getResourceAsStream("demo.ldif"), nodeRolesFile);
- } catch (IOException e) {
- throw new CmsException("Cannot copy demo resource", e);
- }
+ if (!nodeRolesFile.exists())
+ try {
+ FileUtils.copyInputStreamToFile(
+ getClass().getResourceAsStream("demo.ldif"),
+ nodeRolesFile);
+ } catch (IOException e) {
+ throw new CmsException("Cannot copy demo resource", e);
+ }
LdifUserAdmin nodeRoles = new LdifUserAdmin(nodeRolesFile.toURI()
- .toString());
+ .toString(), false);
nodeRoles.setExternalRoles(userAdmin);
nodeRoles.init();
// nodeRoles.createRole(KernelHeader.ROLE_ADMIN, Role.GROUP);
}
+ private Subject logKernel() {
+ final Subject kernelSubject = new Subject();
+ createKeyStoreIfNeeded();
+
+ CallbackHandler cbHandler = new CallbackHandler() {
+
+ @Override
+ public void handle(Callback[] callbacks) throws IOException,
+ UnsupportedCallbackException {
+ // alias
+ ((NameCallback) callbacks[1]).setName(KernelHeader.ROLE_KERNEL);
+ // store pwd
+ ((PasswordCallback) callbacks[2]).setPassword("changeit"
+ .toCharArray());
+ // key pwd
+ ((PasswordCallback) callbacks[3]).setPassword("changeit"
+ .toCharArray());
+ }
+ };
+ try {
+ LoginContext kernelLc = new LoginContext(
+ KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject,
+ cbHandler);
+ kernelLc.login();
+ } catch (LoginException e) {
+ throw new CmsException("Cannot log in kernel", e);
+ }
+ return kernelSubject;
+ }
+
public void publish() {
authenticationManagerReg = bundleContext.registerService(
AuthenticationManager.class, this, null);
- userAdminServiceReg = bundleContext.registerService(
- UserAdminService.class, userAdminService, null);
- userDetailsManagerReg = bundleContext.registerService(
- UserDetailsManager.class, userAdminService, null);
+ // userAdminServiceReg = bundleContext.registerService(
+ // UserAdminService.class, userAdminService, null);
+ // userDetailsManagerReg = bundleContext.registerService(
+ // UserDetailsManager.class, userAdminService, null);
userAdminReg = bundleContext.registerService(UserAdmin.class,
userAdmin, null);
}
void destroy() {
- try {
- userAdminService.destroy();
- } catch (RepositoryException e) {
- log.error("Error while destroying Jackrabbit useradmin");
- }
- userDetailsManagerReg.unregister();
- userAdminServiceReg.unregister();
+ // try {
+ // userAdminService.destroy();
+ // } catch (RepositoryException e) {
+ // log.error("Error while destroying Jackrabbit useradmin");
+ // }
+ // userDetailsManagerReg.unregister();
+ // userAdminServiceReg.unregister();
authenticationManagerReg.unregister();
// userAdmin.destroy();
userAdminReg.unregister();
+
+ // Logout kernel
+ try {
+ LoginContext kernelLc = new LoginContext(
+ KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject);
+ kernelLc.logout();
+ } catch (LoginException e) {
+ throw new CmsException("Cannot log in kernel", e);
+ }
+
+ Security.removeProvider(KernelHeader.SECURITY_PROVIDER);
+ }
+
+ public NodeUserAdmin getUserAdmin() {
+ return userAdmin;
+ }
+
+ public Subject getKernelSubject() {
+ return kernelSubject;
}
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
-// throw new UnsupportedOperationException(
-// "Authentication manager is deprectaed and should not be used.");
- Authentication auth = null;
- if (authentication instanceof InternalAuthentication)
- auth = internalAuth.authenticate(authentication);
- else if (authentication instanceof AnonymousAuthenticationToken)
- auth = anonymousAuth.authenticate(authentication);
- else if (authentication instanceof UsernamePasswordAuthenticationToken)
- auth = userAdminService.authenticate(authentication);
- else if (authentication instanceof OsAuthenticationToken)
- auth = osAuth.authenticate(authentication);
- if (auth == null)
- throw new CmsException("Could not authenticate " + authentication);
- return auth;
+ log.error("Authentication manager is deprectaed and should not be used.");
+ // Authentication auth = null;
+ // if (authentication instanceof InternalAuthentication)
+ // auth = internalAuth.authenticate(authentication);
+ // else if (authentication instanceof AnonymousAuthenticationToken)
+ // auth = anonymousAuth.authenticate(authentication);
+ // else if (authentication instanceof
+ // UsernamePasswordAuthenticationToken)
+ // auth = userAdminService.authenticate(authentication);
+ // else if (authentication instanceof OsAuthenticationToken)
+ // auth = osAuth.authenticate(authentication);
+ // if (auth == null)
+ // throw new CmsException("Could not authenticate " + authentication);
+ throw new ProviderNotFoundException(
+ "Authentication manager is deprectaed and should not be used.");
}
+
+ private void createKeyStoreIfNeeded() {
+ char[] ksPwd = "changeit".toCharArray();
+ char[] keyPwd = Arrays.copyOf(ksPwd, ksPwd.length);
+ File keyStoreFile = new File(KernelUtils.getOsgiInstanceDir(),
+ "node.p12");
+ if (!keyStoreFile.exists()) {
+ try {
+ keyStoreFile.getParentFile().mkdirs();
+ KeyStore keyStore = PkiUtils.getKeyStore(keyStoreFile, ksPwd);
+ PkiUtils.generateSelfSignedCertificate(keyStore,
+ new X500Principal(KernelHeader.ROLE_KERNEL), keyPwd);
+ PkiUtils.saveKeyStore(keyStoreFile, ksPwd, keyStore);
+
+ } catch (Exception e) {
+ throw new CmsException("Cannot create key store "
+ + keyStoreFile, e);
+ }
+ }
+ }
+
}
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.argeo.osgi.useradmin.ArgeoUserAdminException;
+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;
try {
ROLES_BASE = new LdapName(KernelHeader.ROLES_BASEDN);
} catch (InvalidNameException e) {
- throw new ArgeoUserAdminException("Cannot initialize "
+ 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);
//
@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 ArgeoUserAdminException(
+ throw new UserDirectoryException(
"There is already a user admin for " + baseDn);
try {
userAdmins.put(new LdapName(baseDn), userAdmin);
} catch (InvalidNameException e) {
- throw new ArgeoUserAdminException("Badly formatted base DN "
+ throw new UserDirectoryException("Badly formatted base DN "
+ baseDn, e);
}
}
@Override
public synchronized void removeUserAdmin(String baseDn) {
if (baseDn.equals(KernelHeader.ROLES_BASEDN))
- throw new ArgeoUserAdminException("Node roles cannot be removed.");
+ throw new UserDirectoryException("Node roles cannot be removed.");
LdapName base;
try {
base = new LdapName(baseDn);
} catch (InvalidNameException e) {
- throw new ArgeoUserAdminException("Badly formatted base DN "
+ throw new UserDirectoryException("Badly formatted base DN "
+ baseDn, e);
}
if (!userAdmins.containsKey(base))
- throw new ArgeoUserAdminException("There is no user admin for "
+ throw new UserDirectoryException("There is no user admin for "
+ base);
- userAdmins.remove(base);
+ UserAdmin userAdmin = userAdmins.remove(base);
+ if (userAdmin instanceof AbstractUserDirectory)
+ ((AbstractUserDirectory) userAdmin).setSyncRegistry(null);
}
private UserAdmin findUserAdmin(String name) {
try {
return findUserAdmin(new LdapName(name));
} catch (InvalidNameException e) {
- throw new ArgeoUserAdminException("Badly formatted name " + name, e);
+ throw new UserDirectoryException("Badly formatted name " + name, e);
}
}
res.add(userAdmins.get(baseDn));
}
if (res.size() == 0)
- throw new ArgeoUserAdminException("Cannot find user admin for "
+ throw new UserDirectoryException("Cannot find user admin for "
+ name);
if (res.size() > 1)
- throw new ArgeoUserAdminException("Multiple user admin found for "
+ throw new UserDirectoryException("Multiple user admin found for "
+ name);
return res.get(0);
}
+
+ 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);
+ }
+ }
+
}
KERNEL {
com.sun.security.auth.module.UnixLoginModule requisite;
- com.sun.security.auth.module.KeyStoreLoginModule requisite keyStoreURL="${osgi.configuration.area}/node.p12" keyStoreType=PKCS12 keyStoreProvider=BC;
+ com.sun.security.auth.module.KeyStoreLoginModule requisite keyStoreURL="${osgi.instance.area}/node.p12" keyStoreType=PKCS12 keyStoreProvider=BC;
org.argeo.cms.internal.auth.KernelLoginModule requisite;
};
--- /dev/null
+package org.argeo.cms.internal.transaction;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+class SimpleTransaction implements Transaction, Status {
+ private final static Log log = LogFactory.getLog(SimpleTransaction.class);
+
+ private final Xid xid;
+ private int status = Status.STATUS_ACTIVE;
+ private final List<XAResource> xaResources = new ArrayList<XAResource>();
+
+ public SimpleTransaction() {
+ xid = new UuidXid();
+ }
+
+ @Override
+ public synchronized void commit() throws RollbackException,
+ HeuristicMixedException, HeuristicRollbackException,
+ SecurityException, IllegalStateException, SystemException {
+ status = STATUS_PREPARING;
+ for (XAResource xaRes : xaResources) {
+ if (status == STATUS_MARKED_ROLLBACK)
+ break;
+ try {
+ xaRes.prepare(xid);
+ } catch (XAException e) {
+ status = STATUS_MARKED_ROLLBACK;
+ log.error("Cannot prepare " + xaRes + " for " + xid, e);
+ }
+ }
+ if (status == STATUS_MARKED_ROLLBACK) {
+ rollback();
+ throw new RollbackException();
+ }
+ status = STATUS_PREPARED;
+
+ status = STATUS_COMMITTING;
+ for (XAResource xaRes : xaResources) {
+ if (status == STATUS_MARKED_ROLLBACK)
+ break;
+ try {
+ xaRes.commit(xid, false);
+ } catch (XAException e) {
+ status = STATUS_MARKED_ROLLBACK;
+ log.error("Cannot prepare " + xaRes + " for " + xid, e);
+ }
+ }
+ if (status == STATUS_MARKED_ROLLBACK) {
+ rollback();
+ throw new RollbackException();
+ }
+ status = STATUS_COMMITTED;
+ }
+
+ @Override
+ public synchronized boolean delistResource(XAResource xaRes, int flag)
+ throws IllegalStateException, SystemException {
+ return xaResources.remove(xaRes);
+ }
+
+ @Override
+ public synchronized boolean enlistResource(XAResource xaRes)
+ throws RollbackException, IllegalStateException, SystemException {
+ return xaResources.add(xaRes);
+ }
+
+ @Override
+ public synchronized int getStatus() throws SystemException {
+ return status;
+ }
+
+ @Override
+ public void registerSynchronization(Synchronization sync)
+ throws RollbackException, IllegalStateException, SystemException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public synchronized void rollback() throws IllegalStateException,
+ SystemException {
+ status = STATUS_ROLLING_BACK;
+ for (XAResource xaRes : xaResources) {
+ try {
+ xaRes.rollback(xid);
+ } catch (XAException e) {
+ log.error("Cannot rollback " + xaRes + " for " + xid, e);
+ }
+ }
+ status = STATUS_ROLLEDBACK;
+ }
+
+ @Override
+ public void setRollbackOnly() throws IllegalStateException, SystemException {
+ status = STATUS_MARKED_ROLLBACK;
+ }
+
+ @Override
+ public int hashCode() {
+ return xid.hashCode();
+ }
+
+ public Xid getXid() {
+ return xid;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.internal.transaction;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import javax.transaction.UserTransaction;
+import javax.transaction.xa.Xid;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsException;
+
+public class SimpleTransactionManager implements TransactionManager,
+ UserTransaction {
+ private final static Log log = LogFactory
+ .getLog(SimpleTransactionManager.class);
+
+ private ThreadLocal<SimpleTransaction> current = new ThreadLocal<SimpleTransaction>();
+
+ private Map<Xid, SimpleTransaction> knownTransactions = Collections
+ .synchronizedMap(new HashMap<Xid, SimpleTransaction>());
+ private SyncRegistry syncRegistry = new SyncRegistry();
+
+ @Override
+ public void begin() throws NotSupportedException, SystemException {
+ if (getCurrent() != null)
+ throw new NotSupportedException(
+ "Nested transactions are not supported");
+ SimpleTransaction transaction = new SimpleTransaction();
+ knownTransactions.put(transaction.getXid(), transaction);
+ current.set(transaction);
+ if (log.isDebugEnabled())
+ log.debug("Started transaction " + transaction.getXid());
+ }
+
+ @Override
+ public void commit() throws RollbackException, HeuristicMixedException,
+ HeuristicRollbackException, SecurityException,
+ IllegalStateException, SystemException {
+ if (getCurrent() == null)
+ throw new IllegalStateException(
+ "No transaction registered with the current thread.");
+ getCurrent().commit();
+ }
+
+ @Override
+ public int getStatus() throws SystemException {
+ if (getCurrent() == null)
+ return Status.STATUS_NO_TRANSACTION;
+ return getTransaction().getStatus();
+ }
+
+ @Override
+ public Transaction getTransaction() throws SystemException {
+ return getCurrent();
+ }
+
+ protected SimpleTransaction getCurrent() throws SystemException {
+ SimpleTransaction transaction = current.get();
+ if (transaction == null)
+ return null;
+ int status = transaction.getStatus();
+ if (Status.STATUS_COMMITTED == status
+ || Status.STATUS_ROLLEDBACK == status) {
+ current.remove();
+ knownTransactions.remove(transaction.getXid());
+ if (log.isDebugEnabled())
+ log.debug("Completed transaction "
+ + transaction.getXid()
+ + " ["
+ + (status == Status.STATUS_ROLLEDBACK ? "FAILED" : "OK")
+ + "]");
+ return null;
+ }
+ return transaction;
+ }
+
+ @Override
+ public void resume(Transaction tobj) throws InvalidTransactionException,
+ IllegalStateException, SystemException {
+ if (getCurrent() != null)
+ throw new IllegalStateException("Transaction " + current.get()
+ + " already registered");
+ current.set((SimpleTransaction) tobj);
+ }
+
+ @Override
+ public void rollback() throws IllegalStateException, SecurityException,
+ SystemException {
+ if (getCurrent() == null)
+ throw new IllegalStateException(
+ "No transaction registered with the current thread.");
+ getCurrent().rollback();
+ }
+
+ @Override
+ public void setRollbackOnly() throws IllegalStateException, SystemException {
+ if (getCurrent() == null)
+ throw new IllegalStateException(
+ "No transaction registered with the current thread.");
+ getCurrent().setRollbackOnly();
+ }
+
+ @Override
+ public void setTransactionTimeout(int seconds) throws SystemException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Transaction suspend() throws SystemException {
+ Transaction transaction = getCurrent();
+ current.remove();
+ return transaction;
+ }
+
+ public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() {
+ return syncRegistry;
+ }
+
+ private class SyncRegistry implements TransactionSynchronizationRegistry {
+ @Override
+ public Object getTransactionKey() {
+ try {
+ SimpleTransaction transaction = getCurrent();
+ if (transaction == null)
+ return null;
+ return getCurrent().getXid();
+ } catch (SystemException e) {
+ throw new CmsException("Cannot get transaction key", e);
+ }
+ }
+
+ @Override
+ public void putResource(Object key, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object getResource(Object key) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void registerInterposedSynchronization(Synchronization sync) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getTransactionStatus() {
+ try {
+ return getStatus();
+ } catch (SystemException e) {
+ throw new CmsException("Cannot get status", e);
+ }
+ }
+
+ @Override
+ public boolean getRollbackOnly() {
+ try {
+ return getStatus() == Status.STATUS_MARKED_ROLLBACK;
+ } catch (SystemException e) {
+ throw new CmsException("Cannot get status", e);
+ }
+ }
+
+ @Override
+ public void setRollbackOnly() {
+ try {
+ getCurrent().setRollbackOnly();
+ } catch (Exception e) {
+ throw new CmsException("Cannot set rollback only", e);
+ }
+ }
+
+ }
+}
--- /dev/null
+package org.argeo.cms.internal.transaction;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.UUID;
+
+import javax.transaction.xa.Xid;
+
+/**
+ * Implementation of {@link Xid} based on {@link UUID}, using max significant
+ * bits as global transaction id, and least significant bits as branch
+ * qualifier.
+ */
+public class UuidXid implements Xid, Serializable {
+ private static final long serialVersionUID = -5380531989917886819L;
+ public final static int FORMAT = (int) serialVersionUID;
+
+ private final static int BYTES_PER_LONG = Long.SIZE / Byte.SIZE;
+
+ private final int format;
+ private final byte[] globalTransactionId;
+ private final byte[] branchQualifier;
+ private final String uuid;
+ private final int hashCode;
+
+ public UuidXid() {
+ this(UUID.randomUUID());
+ }
+
+ public UuidXid(UUID uuid) {
+ this.format = FORMAT;
+ this.globalTransactionId = uuidToBytes(uuid.getMostSignificantBits());
+ this.branchQualifier = uuidToBytes(uuid.getLeastSignificantBits());
+ this.uuid = uuid.toString();
+ this.hashCode = uuid.hashCode();
+ }
+
+ public UuidXid(Xid xid) {
+ this(xid.getFormatId(), xid.getGlobalTransactionId(), xid
+ .getBranchQualifier());
+ }
+
+ private UuidXid(int format, byte[] globalTransactionId,
+ byte[] branchQualifier) {
+ this.format = format;
+ this.globalTransactionId = globalTransactionId;
+ this.branchQualifier = branchQualifier;
+ this.uuid = bytesToUUID(globalTransactionId, branchQualifier)
+ .toString();
+ this.hashCode = uuid.hashCode();
+ }
+
+ @Override
+ public int getFormatId() {
+ return format;
+ }
+
+ @Override
+ public byte[] getGlobalTransactionId() {
+ return Arrays.copyOf(globalTransactionId, globalTransactionId.length);
+ }
+
+ @Override
+ public byte[] getBranchQualifier() {
+ return Arrays.copyOf(branchQualifier, branchQualifier.length);
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj instanceof UuidXid) {
+ UuidXid that = (UuidXid) obj;
+ return Arrays.equals(globalTransactionId, that.globalTransactionId)
+ && Arrays.equals(branchQualifier, that.branchQualifier);
+ }
+ if (obj instanceof Xid) {
+ Xid that = (Xid) obj;
+ return Arrays.equals(globalTransactionId,
+ that.getGlobalTransactionId())
+ && Arrays
+ .equals(branchQualifier, that.getBranchQualifier());
+ }
+ return uuid.equals(obj.toString());
+ }
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return new UuidXid(format, globalTransactionId, branchQualifier);
+ }
+
+ @Override
+ public String toString() {
+ return uuid;
+ }
+
+ public UUID asUuid() {
+ return bytesToUUID(globalTransactionId, branchQualifier);
+ }
+
+ public static byte[] uuidToBytes(long bits) {
+ ByteBuffer buffer = ByteBuffer.allocate(BYTES_PER_LONG);
+ buffer.putLong(0, bits);
+ return buffer.array();
+ }
+
+ public static UUID bytesToUUID(byte[] most, byte[] least) {
+ if (most.length < BYTES_PER_LONG)
+ most = Arrays.copyOf(most, BYTES_PER_LONG);
+ if (least.length < BYTES_PER_LONG)
+ least = Arrays.copyOf(least, BYTES_PER_LONG);
+ ByteBuffer buffer = ByteBuffer.allocate(2 * BYTES_PER_LONG);
+ buffer.put(most, 0, BYTES_PER_LONG);
+ buffer.put(least, 0, BYTES_PER_LONG);
+ buffer.flip();
+ return new UUID(buffer.getLong(), buffer.getLong());
+ }
+
+ // public static void main(String[] args) {
+ // UUID uuid = UUID.randomUUID();
+ // System.out.println(uuid);
+ // uuid = bytesToUUID(uuidToBytes(uuid.getMostSignificantBits()),
+ // uuidToBytes(uuid.getLeastSignificantBits()));
+ // System.out.println(uuid);
+ // }
+}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdmin;
-
-public abstract class AbstractLdapUserAdmin implements UserAdmin {
- private boolean isReadOnly;
- private URI uri;
-
- private UserAdmin externalRoles;
- private List<String> indexedUserProperties = Arrays.asList(new String[] {
- "uid", "mail", "cn" });
-
- public AbstractLdapUserAdmin() {
- }
-
- public AbstractLdapUserAdmin(URI uri, boolean isReadOnly) {
- this.uri = uri;
- this.isReadOnly = isReadOnly;
- }
-
- public void init() {
-
- }
-
- public void destroy() {
-
- }
-
- /** Returns the {@link Group}s this user is a direct member of. */
- protected abstract List<? extends Group> getDirectGroups(User user);
-
- List<Role> getAllRoles(User user) {
- List<Role> allRoles = new ArrayList<Role>();
- if (user != null) {
- collectRoles(user, allRoles);
- allRoles.add(user);
- } else
- collectAnonymousRoles(allRoles);
- return allRoles;
- }
-
- private void collectRoles(User user, List<Role> allRoles) {
- for (Group group : getDirectGroups(user)) {
- // TODO check for loops
- allRoles.add(group);
- collectRoles(group, allRoles);
- }
- }
-
- private void collectAnonymousRoles(List<Role> allRoles) {
- // TODO gather anonymous roles
- }
-
- protected URI getUri() {
- return uri;
- }
-
- protected void setUri(URI uri) {
- this.uri = uri;
- }
-
- protected List<String> getIndexedUserProperties() {
- return indexedUserProperties;
- }
-
- protected void setIndexedUserProperties(List<String> indexedUserProperties) {
- this.indexedUserProperties = indexedUserProperties;
- }
-
- protected void setReadOnly(boolean isReadOnly) {
- this.isReadOnly = isReadOnly;
- }
-
- public boolean isReadOnly() {
- return isReadOnly;
- }
-
- UserAdmin getExternalRoles() {
- return externalRoles;
- }
-
- public void setExternalRoles(UserAdmin externalRoles) {
- this.externalRoles = externalRoles;
- }
-
-}
--- /dev/null
+package org.argeo.osgi.useradmin;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdmin;
+
+public abstract class AbstractUserDirectory implements UserAdmin {
+ private boolean isReadOnly;
+ private URI uri;
+
+ private UserAdmin externalRoles;
+ private List<String> indexedUserProperties = Arrays.asList(new String[] {
+ "uid", "mail", "cn" });
+
+ private String memberAttributeId = "member";
+ private List<String> credentialAttributeIds = Arrays
+ .asList(new String[] { "userpassword" });
+
+ private TransactionSynchronizationRegistry syncRegistry;
+ private Object editingTransactionKey = null;
+ private TransactionManager transactionManager;
+ private Transaction editingTransaction;
+
+ public AbstractUserDirectory() {
+ }
+
+ public AbstractUserDirectory(URI uri, boolean isReadOnly) {
+ this.uri = uri;
+ this.isReadOnly = isReadOnly;
+ }
+
+ /** Returns the {@link Group}s this user is a direct member of. */
+ protected abstract List<? extends Group> getDirectGroups(User user);
+
+ public void init() {
+
+ }
+
+ public void destroy() {
+
+ }
+
+ boolean isEditing() {
+ if (editingTransactionKey == null)
+ return false;
+ Object currentTrKey = syncRegistry.getTransactionKey();
+ if (currentTrKey == null)
+ return false;
+ return editingTransactionKey.equals(currentTrKey);
+ }
+
+ void checkEdit() {
+ Object currentTrKey = syncRegistry.getTransactionKey();
+ if (currentTrKey == null)
+ throw new UserDirectoryException(
+ "A transaction needs to be active in order to edit");
+ if (editingTransactionKey == null) {
+ editingTransactionKey = currentTrKey;
+ XAResource xaRes = getXAResource();
+ if (xaRes != null)
+ try {
+ transactionManager.getTransaction().enlistResource(xaRes);
+ } catch (Exception e) {
+ throw new UserDirectoryException("Cannot enlist " + this, e);
+ }
+ } else {
+ if (!editingTransactionKey.equals(currentTrKey))
+ throw new UserDirectoryException("Transaction "
+ + editingTransactionKey + " already editing");
+ }
+ }
+
+ List<Role> getAllRoles(User user) {
+ List<Role> allRoles = new ArrayList<Role>();
+ if (user != null) {
+ collectRoles(user, allRoles);
+ allRoles.add(user);
+ } else
+ collectAnonymousRoles(allRoles);
+ return allRoles;
+ }
+
+ private void collectRoles(User user, List<Role> allRoles) {
+ for (Group group : getDirectGroups(user)) {
+ // TODO check for loops
+ allRoles.add(group);
+ collectRoles(group, allRoles);
+ }
+ }
+
+ private void collectAnonymousRoles(List<Role> allRoles) {
+ // TODO gather anonymous roles
+ }
+
+ public XAResource getXAResource() {
+ return null;
+ }
+
+ String getMemberAttributeId() {
+ return memberAttributeId;
+ }
+
+ List<String> getCredentialAttributeIds() {
+ return credentialAttributeIds;
+ }
+
+ protected URI getUri() {
+ return uri;
+ }
+
+ protected void setUri(URI uri) {
+ this.uri = uri;
+ }
+
+ protected List<String> getIndexedUserProperties() {
+ return indexedUserProperties;
+ }
+
+ protected void setIndexedUserProperties(List<String> indexedUserProperties) {
+ this.indexedUserProperties = indexedUserProperties;
+ }
+
+ protected void setReadOnly(boolean isReadOnly) {
+ this.isReadOnly = isReadOnly;
+ }
+
+ public boolean isReadOnly() {
+ return isReadOnly;
+ }
+
+ UserAdmin getExternalRoles() {
+ return externalRoles;
+ }
+
+ public void setExternalRoles(UserAdmin externalRoles) {
+ this.externalRoles = externalRoles;
+ }
+
+ public void setSyncRegistry(TransactionSynchronizationRegistry syncRegistry) {
+ this.syncRegistry = syncRegistry;
+ }
+
+ public void setTransactionManager(TransactionManager transactionManager) {
+ this.transactionManager = transactionManager;
+ }
+
+}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import org.osgi.service.useradmin.UserAdmin;
-
-/**
- * Exceptions related to Argeo's implementation of OSGi {@link UserAdmin}
- * service.
- */
-public class ArgeoUserAdminException extends RuntimeException {
- private static final long serialVersionUID = 1419352360062048603L;
-
- public ArgeoUserAdminException(String message) {
- super(message);
- }
-
- public ArgeoUserAdminException(String message, Throwable e) {
- super(message, e);
- }
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttribute;
-
-class AttributeDictionary extends Dictionary<String,Object> {
- private final Attributes attributes;
- private final List<String> effectiveKeys = new ArrayList<String>();
- private final List<String> attrFilter;
- private final Boolean includeFilter;
-
- public AttributeDictionary(Attributes attributes, List<String> attrFilter,
- Boolean includeFilter) {
- this.attributes = attributes;
- this.attrFilter = attrFilter;
- this.includeFilter = includeFilter;
- try {
- NamingEnumeration<String> ids = attributes.getIDs();
- while (ids.hasMore()) {
- String id = ids.next();
- if (includeFilter && attrFilter.contains(id))
- effectiveKeys.add(id);
- else if (!includeFilter && !attrFilter.contains(id))
- effectiveKeys.add(id);
- }
- } catch (NamingException e) {
- throw new ArgeoUserAdminException(
- "Cannot initialise attribute dictionary", e);
- }
- }
-
- @Override
- public int size() {
- return effectiveKeys.size();
- }
-
- @Override
- public boolean isEmpty() {
- return effectiveKeys.size() == 0;
- }
-
- @Override
- public Enumeration<String> keys() {
- return Collections.enumeration(effectiveKeys);
- }
-
- @Override
- public Enumeration<Object> elements() {
- final Iterator<String> it = effectiveKeys.iterator();
- return new Enumeration<Object>() {
-
- @Override
- public boolean hasMoreElements() {
- return it.hasNext();
- }
-
- @Override
- public Object nextElement() {
- String key = it.next();
- try {
- return attributes.get(key).get();
- } catch (NamingException e) {
- throw new ArgeoUserAdminException(
- "Cannot get value for key " + key, e);
- }
- }
-
- };
- }
-
- @Override
- public Object get(Object key) {
- try {
- Attribute attr = attributes.get(key.toString());
- if (attr == null)
- return null;
- return attr.get();
- } catch (NamingException e) {
- throw new ArgeoUserAdminException("Cannot get value for attribute "
- + key, e);
- }
- }
-
- @Override
- public Object put(String key, Object value) {
- if (!(value instanceof String || value instanceof byte[]))
- throw new IllegalArgumentException("Value must be String or byte[]");
-
- if (includeFilter && !attrFilter.contains(key))
- throw new IllegalArgumentException("Key " + key + " not included");
- else if (!includeFilter && attrFilter.contains(key))
- throw new IllegalArgumentException("Key " + key + " excluded");
-
- try {
- Attribute attribute = attributes.get(key.toString());
- attribute = new BasicAttribute(key.toString());
- attribute.add(value);
- Attribute previousAttribute = attributes.put(attribute);
- if (previousAttribute != null)
- return previousAttribute.get();
- else
- return null;
- } catch (NamingException e) {
- throw new ArgeoUserAdminException("Cannot get value for attribute "
- + key, e);
- }
- }
-
- @Override
- public Object remove(Object key) {
- if (includeFilter && !attrFilter.contains(key))
- throw new IllegalArgumentException("Key " + key + " not included");
- else if (!includeFilter && attrFilter.contains(key))
- throw new IllegalArgumentException("Key " + key + " excluded");
-
- try {
- Attribute attr = attributes.remove(key.toString());
- if (attr != null)
- return attr.get();
- else
- return null;
- } catch (NamingException e) {
- throw new ArgeoUserAdminException("Cannot remove attribute " + key,
- e);
- }
- }
-}
--- /dev/null
+package org.argeo.osgi.useradmin;
+
+import java.util.List;
+
+import javax.naming.ldap.LdapName;
+
+import org.osgi.service.useradmin.Group;
+
+public interface DirectoryGroup extends Group, DirectoryUser {
+ List<LdapName> getMemberNames();
+}
--- /dev/null
+package org.argeo.osgi.useradmin;
+
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+
+import org.osgi.service.useradmin.User;
+
+interface DirectoryUser extends User {
+ LdapName getDn();
+
+ Attributes getAttributes();
+}
--- /dev/null
+package org.argeo.osgi.useradmin;
+
+import org.osgi.service.useradmin.Role;
+
+public interface EditorRole extends Role {
+ public static final int EDITOR = -1;
+
+
+}
*/
public interface LdapNames {
public final static String LDAP_PREFIX = "ldap:";
-
+
// Attributes
public final static String LDAP_CN = LDAP_PREFIX + "cn";
+ public final static String LDAP_SN = LDAP_PREFIX + "sn";
public final static String LDAP_UID = LDAP_PREFIX + "uid";
public final static String LDAP_DISPLAY_NAME = LDAP_PREFIX + "displayName";
+
}
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.User;
-public class LdapUserAdmin extends AbstractLdapUserAdmin {
+public class LdapUserAdmin extends AbstractUserDirectory {
private final static Log log = LogFactory.getLog(LdapUserAdmin.class);
private String baseDn = "dc=example,dc=com";
log.debug(initialLdapContext.getAttributes(
"uid=root,ou=users,dc=example,dc=com").get("cn"));
} catch (Exception e) {
- throw new ArgeoUserAdminException("Cannot connect to LDAP", e);
+ throw new UserDirectoryException("Cannot connect to LDAP", e);
}
}
if (attrs.get("objectClass").contains("groupOfNames"))
res = new LdifGroup(this, new LdapName(name), attrs);
else if (attrs.get("objectClass").contains("inetOrgPerson"))
- res = new LdifUser(new LdapName(name), attrs);
+ res = new LdifUser(this, new LdapName(name), attrs);
else
- throw new ArgeoUserAdminException("Unsupported LDAP type for "
+ throw new UserDirectoryException("Unsupported LDAP type for "
+ name);
return res;
} catch (NamingException e) {
- throw new ArgeoUserAdminException("Cannot get role for " + name, e);
+ throw new UserDirectoryException("Cannot get role for " + name, e);
}
}
role = new LdifGroup(this, toDn(searchBase, searchResult),
attrs);
else if (attrs.get("objectClass").contains("inetOrgPerson"))
- role = new LdifUser(toDn(searchBase, searchResult), attrs);
+ role = new LdifUser(this, toDn(searchBase, searchResult),
+ attrs);
else
- throw new ArgeoUserAdminException(
+ throw new UserDirectoryException(
"Unsupported LDAP type for "
+ searchResult.getName());
res.add(role);
}
return res.toArray(new Role[res.size()]);
} catch (Exception e) {
- throw new ArgeoUserAdminException("Cannot get roles for filter "
+ throw new UserDirectoryException("Cannot get roles for filter "
+ filter, e);
}
}
}
if (searchResult == null)
return null;
- return new LdifUser(toDn(searchBase, searchResult),
+ return new LdifUser(this, toDn(searchBase, searchResult),
searchResult.getAttributes());
} catch (Exception e) {
- throw new ArgeoUserAdminException("Cannot get user with " + key
+ throw new UserDirectoryException("Cannot get user with " + key
+ "=" + value, e);
}
}
if (displayName == null)
displayName = user.getName();
if (displayName == null)
- throw new ArgeoUserAdminException(
+ throw new UserDirectoryException(
"Cannot set display name for " + user);
this.displayName = displayName.toString();
}
import javax.naming.directory.Attributes;
import javax.naming.ldap.LdapName;
-import org.osgi.service.useradmin.Group;
import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.UserAdmin;
-public class LdifGroup extends LdifUser implements Group {
- // optimisation
- // List<Role> directMembers = null;
+public class LdifGroup extends LdifUser implements DirectoryGroup {
+ private final String memberAttributeId;
- private final UserAdmin userAdmin;
- private String memberAttrName = "member";
-
- public LdifGroup(UserAdmin userAdmin, LdapName dn, Attributes attributes) {
- super(dn, attributes);
- this.userAdmin = userAdmin;
+ public LdifGroup(AbstractUserDirectory userAdmin, LdapName dn,
+ Attributes attributes) {
+ super(userAdmin, dn, attributes);
+ memberAttributeId = userAdmin.getMemberAttributeId();
}
@Override
public boolean addMember(Role role) {
- Attribute member = getAttributes().get(memberAttrName);
+ Attribute member = getAttributes().get(memberAttributeId);
if (member != null) {
if (member.contains(role.getName()))
return false;
} else
- getAttributes().put(memberAttrName, role.getName());
- // directMembers.add(role);
- // if (role instanceof LdifUser)
- // ((LdifUser) role).directMemberOf.add(this);
+ getAttributes().put(memberAttributeId, role.getName());
return true;
}
@Override
public boolean removeMember(Role role) {
- Attribute member = getAttributes().get(memberAttrName);
+ Attribute member = getAttributes().get(memberAttributeId);
if (member != null) {
if (!member.contains(role.getName()))
return false;
member.remove(role.getName());
- // directMembers.remove(role);
- // if (role instanceof LdifUser)
- // ((LdifUser) role).directMemberOf.remove(this);
return true;
} else
return false;
public Role[] getMembers() {
List<Role> directMembers = new ArrayList<Role>();
for (LdapName ldapName : getMemberNames()) {
- Role role = userAdmin.getRole(ldapName.toString());
- if (role == null && userAdmin instanceof AbstractLdapUserAdmin) {
- AbstractLdapUserAdmin ua = (AbstractLdapUserAdmin) userAdmin;
- if (ua.getExternalRoles() != null)
- role = ua.getExternalRoles().getRole(ldapName.toString());
+ Role role = getUserAdmin().getRole(ldapName.toString());
+ if (role == null) {
+ if (getUserAdmin().getExternalRoles() != null)
+ role = getUserAdmin().getExternalRoles().getRole(
+ ldapName.toString());
}
if (role == null)
- throw new ArgeoUserAdminException("No role found for "
+ throw new UserDirectoryException("No role found for "
+ ldapName);
-
- // role.directMemberOf.add(group);
- // if (!directMemberOf.containsKey(role.getDn()))
- // directMemberOf.put(role.getDn(), new ArrayList<LdifGroup>());
- // directMemberOf.get(role.getDn()).add(group);
directMembers.add(role);
}
return directMembers.toArray(new Role[directMembers.size()]);
- // if (directMembers != null)
- // return directMembers.toArray(new Role[directMembers.size()]);
- // else
- // throw new ArgeoUserAdminException("Members have not been loaded.");
-
- // Attribute memberAttribute = getAttributes().get(memberAttrName);
- // if (memberAttribute == null)
- // return new Role[0];
- // try {
- // List<Role> roles = new ArrayList<Role>();
- // NamingEnumeration values = memberAttribute.getAll();
- // while (values.hasMore()) {
- // LdapName dn = new LdapName(values.next().toString());
- // roles.add(new LdifUser(dn, null));
- // }
- // return roles.toArray(new Role[roles.size()]);
- // } catch (Exception e) {
- // throw new ArgeoUserAdminException("Cannot get members", e);
- // }
}
- // void loadMembers(LdifUserAdmin userAdmin) {
- // directMembers = new ArrayList<Role>();
- // for (LdapName ldapName : getMemberNames()) {
- // LdifUser role;
- // if (userAdmin.groups.containsKey(ldapName))
- // role = userAdmin.groups.get(ldapName);
- // else if (userAdmin.users.containsKey(ldapName))
- // role = userAdmin.users.get(ldapName);
- // else
- // throw new ArgeoUserAdminException("No role found for "
- // + ldapName);
- // role.directMemberOf.add(this);
- // directMembers.add(role);
- // }
- // }
-
- List<LdapName> getMemberNames() {
- Attribute memberAttribute = getAttributes().get(memberAttrName);
+ @Override
+ public List<LdapName> getMemberNames() {
+ Attribute memberAttribute = getAttributes().get(memberAttributeId);
if (memberAttribute == null)
return new ArrayList<LdapName>();
try {
}
return roles;
} catch (Exception e) {
- throw new ArgeoUserAdminException("Cannot get members", e);
+ throw new UserDirectoryException("Cannot get members", e);
}
}
public int getType() {
return GROUP;
}
-
- public String getMemberAttrName() {
- return memberAttrName;
- }
-
}
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Iterator;
import java.util.List;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
import javax.naming.ldap.LdapName;
-import org.osgi.service.useradmin.User;
-
-class LdifUser implements User {
- // optimisation
- //List<LdifGroup> directMemberOf = new ArrayList<LdifGroup>();
+class LdifUser implements DirectoryUser {
+ private final AbstractUserDirectory userAdmin;
private final LdapName dn;
- private Attributes attributes;
+
+ private final boolean frozen;
+ private Attributes publishedAttributes;
+ private Attributes modifiedAttributes = null;
private final AttributeDictionary properties;
private final AttributeDictionary credentials;
- private List<String> credentialAttributes = Arrays
- .asList(new String[] { "userpassword" });
+ LdifUser(AbstractUserDirectory userAdmin, LdapName dn, Attributes attributes) {
+ this(userAdmin, dn, attributes, false);
+ }
- LdifUser(LdapName dn, Attributes attributes) {
+ private LdifUser(AbstractUserDirectory userAdmin, LdapName dn,
+ Attributes attributes, boolean frozen) {
+ this.userAdmin = userAdmin;
this.dn = dn;
- this.attributes = attributes;
- properties = new AttributeDictionary(attributes, credentialAttributes,
- false);
- credentials = new AttributeDictionary(attributes, credentialAttributes,
- true);
+ this.publishedAttributes = attributes;
+ properties = new AttributeDictionary(false);
+ credentials = new AttributeDictionary(true);
+ this.frozen = frozen;
}
@Override
return false;
}
- protected LdapName getDn() {
+ @Override
+ public LdapName getDn() {
return dn;
}
- protected Attributes getAttributes() {
- return attributes;
+ @Override
+ public synchronized Attributes getAttributes() {
+ return isEditing() ? modifiedAttributes : publishedAttributes;
+ }
+
+ protected synchronized boolean isEditing() {
+ return userAdmin.isEditing() && modifiedAttributes != null;
+ }
+
+ protected synchronized void startEditing() {
+ if (frozen)
+ throw new UserDirectoryException("Cannot edit frozen view");
+ if (getUserAdmin().isReadOnly())
+ throw new UserDirectoryException("User directory is read-only");
+ assert modifiedAttributes == null;
+ modifiedAttributes = (Attributes) publishedAttributes.clone();
+ }
+
+ protected synchronized void stopEditing(boolean apply) {
+ assert modifiedAttributes != null;
+ if (apply)
+ publishedAttributes = modifiedAttributes;
+ modifiedAttributes = null;
+ }
+
+ public DirectoryUser getPublished() {
+ return new LdifUser(userAdmin, dn, publishedAttributes, true);
}
@Override
public String toString() {
return dn.toString();
}
+
+ protected AbstractUserDirectory getUserAdmin() {
+ return userAdmin;
+ }
+
+ private class AttributeDictionary extends Dictionary<String, Object> {
+ private final List<String> effectiveKeys = new ArrayList<String>();
+ private final List<String> attrFilter;
+ private final Boolean includeFilter;
+
+ public AttributeDictionary(Boolean includeFilter) {
+ this.attrFilter = userAdmin.getCredentialAttributeIds();
+ this.includeFilter = includeFilter;
+ try {
+ NamingEnumeration<String> ids = getAttributes().getIDs();
+ while (ids.hasMore()) {
+ String id = ids.next();
+ if (includeFilter && attrFilter.contains(id))
+ effectiveKeys.add(id);
+ else if (!includeFilter && !attrFilter.contains(id))
+ effectiveKeys.add(id);
+ }
+ } catch (NamingException e) {
+ throw new UserDirectoryException(
+ "Cannot initialise attribute dictionary", e);
+ }
+ }
+
+ @Override
+ public int size() {
+ return effectiveKeys.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return effectiveKeys.size() == 0;
+ }
+
+ @Override
+ public Enumeration<String> keys() {
+ return Collections.enumeration(effectiveKeys);
+ }
+
+ @Override
+ public Enumeration<Object> elements() {
+ final Iterator<String> it = effectiveKeys.iterator();
+ return new Enumeration<Object>() {
+
+ @Override
+ public boolean hasMoreElements() {
+ return it.hasNext();
+ }
+
+ @Override
+ public Object nextElement() {
+ String key = it.next();
+ try {
+ return getAttributes().get(key).get();
+ } catch (NamingException e) {
+ throw new UserDirectoryException(
+ "Cannot get value for key " + key, e);
+ }
+ }
+
+ };
+ }
+
+ @Override
+ public Object get(Object key) {
+ try {
+ Attribute attr = getAttributes().get(key.toString());
+ if (attr == null)
+ return null;
+ return attr.get();
+ } catch (NamingException e) {
+ throw new UserDirectoryException(
+ "Cannot get value for attribute " + key, e);
+ }
+ }
+
+ @Override
+ public Object put(String key, Object value) {
+ userAdmin.checkEdit();
+ if (!isEditing())
+ startEditing();
+
+ if (!(value instanceof String || value instanceof byte[]))
+ throw new IllegalArgumentException(
+ "Value must be String or byte[]");
+
+ if (includeFilter && !attrFilter.contains(key))
+ throw new IllegalArgumentException("Key " + key
+ + " not included");
+ else if (!includeFilter && attrFilter.contains(key))
+ throw new IllegalArgumentException("Key " + key + " excluded");
+
+ try {
+ Attribute attribute = modifiedAttributes.get(key.toString());
+ attribute = new BasicAttribute(key.toString());
+ attribute.add(value);
+ Attribute previousAttribute = modifiedAttributes.put(attribute);
+ if (previousAttribute != null)
+ return previousAttribute.get();
+ else
+ return null;
+ } catch (NamingException e) {
+ throw new UserDirectoryException(
+ "Cannot get value for attribute " + key, e);
+ }
+ }
+
+ @Override
+ public Object remove(Object key) {
+ userAdmin.checkEdit();
+ if (!isEditing())
+ startEditing();
+
+ if (includeFilter && !attrFilter.contains(key))
+ throw new IllegalArgumentException("Key " + key
+ + " not included");
+ else if (!includeFilter && attrFilter.contains(key))
+ throw new IllegalArgumentException("Key " + key + " excluded");
+
+ try {
+ Attribute attr = modifiedAttributes.remove(key.toString());
+ if (attr != null)
+ return attr.get();
+ else
+ return null;
+ } catch (NamingException e) {
+ throw new UserDirectoryException("Cannot remove attribute "
+ + key, e);
+ }
+ }
+ }
+
}
import javax.naming.directory.BasicAttributes;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
import org.apache.commons.io.IOUtils;
import org.osgi.framework.Filter;
import org.osgi.service.useradmin.User;
/** User admin implementation using LDIF file(s) as backend. */
-public class LdifUserAdmin extends AbstractLdapUserAdmin {
+public class LdifUserAdmin extends AbstractUserDirectory {
SortedMap<LdapName, LdifUser> users = new TreeMap<LdapName, LdifUser>();
SortedMap<LdapName, LdifGroup> groups = new TreeMap<LdapName, LdifGroup>();
// private Map<LdapName, List<LdifGroup>> directMemberOf = new
// TreeMap<LdapName, List<LdifGroup>>();
+ private XaRes xaRes = new XaRes();
public LdifUserAdmin(String uri) {
- this(uri, true);
+ this(uri, readOnlyDefault(uri));
}
public LdifUserAdmin(String uri, boolean isReadOnly) {
try {
setUri(new URI(uri));
} catch (URISyntaxException e) {
- throw new ArgeoUserAdminException("Invalid URI " + uri, e);
+ throw new UserDirectoryException("Invalid URI " + uri, e);
}
- if (!isReadOnly && !getUri().getScheme().equals("file:"))
+ if (!isReadOnly && !getUri().getScheme().equals("file"))
throw new UnsupportedOperationException(getUri().getScheme()
- + "not supported read-write.");
+ + " not supported read-write.");
+
+ }
+
+ public LdifUserAdmin(URI uri, boolean isReadOnly) {
+ setReadOnly(isReadOnly);
+ setUri(uri);
+ if (!isReadOnly && !getUri().getScheme().equals("file"))
+ throw new UnsupportedOperationException(getUri().getScheme()
+ + " not supported read-write.");
}
setUri(null);
}
+ private static boolean readOnlyDefault(String uriStr) {
+ URI uri;
+ try {
+ uri = new URI(uriStr);
+ } catch (Exception e) {
+ throw new UserDirectoryException("Invalid URI " + uriStr, e);
+ }
+ if (uri.getScheme().equals("file")) {
+ File file = new File(uri);
+ return !file.canWrite();
+ }
+ return true;
+ }
+
public void init() {
try {
load(getUri().toURL().openStream());
} catch (Exception e) {
- throw new ArgeoUserAdminException("Cannot open URL " + getUri(), e);
+ throw new UserDirectoryException("Cannot open URL " + getUri(), e);
}
}
public void save() {
if (getUri() == null || isReadOnly())
- throw new ArgeoUserAdminException("Cannot save LDIF user admin");
+ throw new UserDirectoryException("Cannot save LDIF user admin");
try (FileOutputStream out = new FileOutputStream(new File(getUri()))) {
save(out);
} catch (IOException e) {
- throw new ArgeoUserAdminException("Cannot save user admin to "
+ throw new UserDirectoryException("Cannot save user admin to "
+ getUri(), e);
}
}
objectClasses: while (objectClasses.hasMore()) {
String objectClass = objectClasses.next().toString();
if (objectClass.equals("inetOrgPerson")) {
- users.put(key, new LdifUser(key, attributes));
+ users.put(key, new LdifUser(this, key, attributes));
break objectClasses;
} else if (objectClass.equals("groupOfNames")) {
groups.put(key, new LdifGroup(this, key, attributes));
}
// optimise
-// for (LdifGroup group : groups.values())
-// loadMembers(group);
+ // for (LdifGroup group : groups.values())
+ // loadMembers(group);
// indexes
for (String attr : getIndexedUserProperties())
LdifUser otherUser = userIndexes.get(attr).put(
value.toString(), user);
if (otherUser != null)
- throw new ArgeoUserAdminException("User " + user
+ throw new UserDirectoryException("User " + user
+ " and user " + otherUser
+ " both have property " + attr
+ " set to " + value);
}
}
} catch (Exception e) {
- throw new ArgeoUserAdminException(
+ throw new UserDirectoryException(
"Cannot load user admin service from LDIF", e);
}
}
try {
LdapName dn = new LdapName(name);
if (users.containsKey(dn) || groups.containsKey(dn))
- throw new ArgeoUserAdminException("Already a role " + name);
+ throw new UserDirectoryException("Already a role " + name);
BasicAttributes attrs = new BasicAttributes();
attrs.put("dn", dn.toString());
attrs.put(nameRdn.getType(), nameRdn.getValue());
LdifUser newRole;
if (type == Role.USER) {
- newRole = new LdifUser(dn, attrs);
+ newRole = new LdifUser(this, dn, attrs);
users.put(dn, newRole);
} else if (type == Role.GROUP) {
newRole = new LdifGroup(this, dn, attrs);
groups.put(dn, (LdifGroup) newRole);
} else
- throw new ArgeoUserAdminException("Unsupported type " + type);
+ throw new UserDirectoryException("Unsupported type " + type);
return newRole;
} catch (InvalidNameException e) {
- throw new ArgeoUserAdminException("Cannot create role " + name, e);
+ throw new UserDirectoryException("Cannot create role " + name, e);
}
}
else if (groups.containsKey(dn))
role = groups.remove(dn);
else
- throw new ArgeoUserAdminException("There is no role " + name);
+ throw new UserDirectoryException("There is no role " + name);
if (role == null)
return false;
for (LdifGroup group : getDirectGroups(role)) {
-// group.directMembers.remove(role);
- group.getAttributes().get(group.getMemberAttrName())
+ // group.directMembers.remove(role);
+ group.getAttributes().get(getMemberAttributeId())
.remove(dn.toString());
}
if (role instanceof LdifGroup) {
}
return true;
} catch (InvalidNameException e) {
- throw new ArgeoUserAdminException("Cannot create role " + name, e);
+ throw new UserDirectoryException("Cannot create role " + name, e);
}
}
// throw new UnsupportedOperationException();
}
-// protected void loadMembers(LdifGroup group) {
-// group.directMembers = new ArrayList<Role>();
-// for (LdapName ldapName : group.getMemberNames()) {
-// LdifUser role = null;
-// if (groups.containsKey(ldapName))
-// role = groups.get(ldapName);
-// else if (users.containsKey(ldapName))
-// role = users.get(ldapName);
-// else {
-// if (getExternalRoles() != null)
-// role = (LdifUser) getExternalRoles().getRole(
-// ldapName.toString());
-// if (role == null)
-// throw new ArgeoUserAdminException("No role found for "
-// + ldapName);
-// }
-// // role.directMemberOf.add(group);
-// // if (!directMemberOf.containsKey(role.getDn()))
-// // directMemberOf.put(role.getDn(), new ArrayList<LdifGroup>());
-// // directMemberOf.get(role.getDn()).add(group);
-// group.directMembers.add(role);
-// }
-// }
+ // protected void loadMembers(LdifGroup group) {
+ // group.directMembers = new ArrayList<Role>();
+ // for (LdapName ldapName : group.getMemberNames()) {
+ // LdifUser role = null;
+ // if (groups.containsKey(ldapName))
+ // role = groups.get(ldapName);
+ // else if (users.containsKey(ldapName))
+ // role = users.get(ldapName);
+ // else {
+ // if (getExternalRoles() != null)
+ // role = (LdifUser) getExternalRoles().getRole(
+ // ldapName.toString());
+ // if (role == null)
+ // throw new ArgeoUserAdminException("No role found for "
+ // + ldapName);
+ // }
+ // // role.directMemberOf.add(group);
+ // // if (!directMemberOf.containsKey(role.getDn()))
+ // // directMemberOf.put(role.getDn(), new ArrayList<LdifGroup>());
+ // // directMemberOf.get(role.getDn()).add(group);
+ // group.directMembers.add(role);
+ // }
+ // }
@Override
protected List<LdifGroup> getDirectGroups(User user) {
try {
dn = new LdapName(user.getName());
} catch (InvalidNameException e) {
- throw new ArgeoUserAdminException("Badly formatted user name "
+ throw new UserDirectoryException("Badly formatted user name "
+ user.getName(), e);
}
// return Collections.EMPTY_LIST;
}
+ @Override
+ public XAResource getXAResource() {
+ return xaRes;
+ }
+
+ private class XaRes implements XAResource {
+
+ @Override
+ public void commit(Xid xid, boolean onePhase) throws XAException {
+ save();
+ }
+
+ @Override
+ public void end(Xid xid, int flags) throws XAException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void forget(Xid xid) throws XAException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public int getTransactionTimeout() throws XAException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public boolean isSameRM(XAResource xares) throws XAException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public int prepare(Xid xid) throws XAException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public Xid[] recover(int flag) throws XAException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void rollback(Xid xid) throws XAException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean setTransactionTimeout(int seconds) throws XAException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void start(Xid xid, int flags) throws XAException {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
}
writer.append('\n');
writer.flush();
} catch (NamingException e) {
- throw new ArgeoUserAdminException("Cannot write LDIF", e);
+ throw new UserDirectoryException("Cannot write LDIF", e);
}
}
--- /dev/null
+package org.argeo.osgi.useradmin;
+
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.UserAdmin;
+
+public interface UserAdminWorkingCopy extends UserAdmin {
+ public void commit();
+
+ public void rollback();
+
+ public Boolean isEditable(Role role);
+
+ public <T extends Role> T getPublished(T role);
+}
--- /dev/null
+package org.argeo.osgi.useradmin;
+
+import org.osgi.service.useradmin.UserAdmin;
+
+/**
+ * Exceptions related to Argeo's implementation of OSGi {@link UserAdmin}
+ * service.
+ */
+public class UserDirectoryException extends RuntimeException {
+ private static final long serialVersionUID = 1419352360062048603L;
+
+ public UserDirectoryException(String message) {
+ super(message);
+ }
+
+ public UserDirectoryException(String message, Throwable e) {
+ super(message, e);
+ }
+}
--- /dev/null
+package org.argeo.osgi.useradmin;
+
+import javax.transaction.UserTransaction;
+
+import org.osgi.service.useradmin.UserAdmin;
+
+class UserDirectoryTransaction {
+ static ThreadLocal<UserDirectoryTransaction> current = new ThreadLocal<UserDirectoryTransaction>();
+
+ private UserAdmin userAdmin;
+
+ private UserTransaction userTransaction;
+
+ public UserDirectoryTransaction(UserAdmin userAdmin) {
+ this.userAdmin = userAdmin;
+ if (current.get() != null)
+ throw new UserDirectoryException("Transaction " + current.get()
+ + " already active.");
+ current.set(this);
+ }
+
+ public void setUserTransaction(UserTransaction userTransaction) {
+ this.userTransaction = userTransaction;
+ }
+
+}
import java.util.HashMap;
import java.util.Map;
-import org.argeo.osgi.useradmin.AbstractLdapUserAdmin;
-import org.argeo.osgi.useradmin.ArgeoUserAdminException;
+import org.argeo.osgi.useradmin.AbstractUserDirectory;
+import org.argeo.osgi.useradmin.UserDirectoryException;
import org.argeo.osgi.useradmin.LdapUserAdmin;
import org.argeo.osgi.useradmin.LdifUserAdmin;
import org.argeo.osgi.useradmin.UserAdminAggregator;
Dictionary<String, ?> properties) throws ConfigurationException {
String baseDn = properties.get("baseDn").toString();
String userAdminUri = properties.get("uri").toString();
- AbstractLdapUserAdmin userAdmin;
+ AbstractUserDirectory userAdmin;
if (userAdminUri.startsWith("ldap"))
userAdmin = new LdapUserAdmin(userAdminUri);
else
if (index.containsKey(pid))
userAdminAggregator.removeUserAdmin(index.get(pid));
else
- throw new ArgeoUserAdminException("No user admin registered for "
+ throw new UserDirectoryException("No user admin registered for "
+ pid);
index.remove(pid);
}
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.SecureRandom;
-import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Date;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
public class PkiUtils {
private final static String SECURITY_PROVIDER;
static {
- Security.addProvider(new BouncyCastleProvider());
+ // Security.addProvider(new BouncyCastleProvider());
SECURITY_PROVIDER = "BC";
}