Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2013-09-20 06:50:20 -0400
committerEike Stepper2013-09-20 06:50:20 -0400
commit6e4718788e24cefc9c06f0e73fba75858da6f2d0 (patch)
tree47bdd7fbd228b0d465499eac5e47122f06b7790d
parent3faadda34ad1992cd06a5c8b74ba3c1c01568299 (diff)
downloadcdo-6e4718788e24cefc9c06f0e73fba75858da6f2d0.tar.gz
cdo-6e4718788e24cefc9c06f0e73fba75858da6f2d0.tar.xz
cdo-6e4718788e24cefc9c06f0e73fba75858da6f2d0.zip
[417684] [Security] Provide a HomeFolderHandler
https://bugs.eclipse.org/bugs/show_bug.cgi?id=417684
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java28
-rw-r--r--plugins/org.eclipse.emf.cdo.server.security/plugin.xml8
-rw-r--r--plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java99
-rw-r--r--plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/security/SecurityManagerUtil.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/AnnotationHandler.java21
-rw-r--r--plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/HomeFolderHandler.java213
-rw-r--r--plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/InternalSecurityManager.java66
-rw-r--r--plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/SecurityManagerFactory.java63
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java26
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java10
-rw-r--r--plugins/org.eclipse.net4j.util/.settings/.api_filters9
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ArrayUtil.java77
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/StringUtil.java50
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IManagedContainer.java14
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IManagedContainerFactory.java12
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/ManagedContainer.java14
16 files changed, 661 insertions, 54 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java
index 0b9dfadc51..64258e28b0 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java
@@ -36,6 +36,7 @@ import org.eclipse.emf.ecore.EClass;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -60,6 +61,8 @@ public class HibernateRawCommitContext implements InternalCommitContext
private boolean usingEtypes;
+ private Map<Object, Object> data;
+
public CDORevision getRevision(CDOID id)
{
for (CDORevision cdoRevision : newObjects)
@@ -341,4 +344,29 @@ public class HibernateRawCommitContext implements InternalCommitContext
{
return null;
}
+
+ public <T> T getData(Object key)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ T result = (T)data.get(key);
+ return result;
+ }
+
+ public synchronized <T extends Object> T setData(Object key, T value)
+ {
+ if (data == null)
+ {
+ data = new HashMap<Object, Object>();
+ }
+
+ @SuppressWarnings("unchecked")
+ T old = (T)data.put(key, value);
+ return old;
+ }
+
}
diff --git a/plugins/org.eclipse.emf.cdo.server.security/plugin.xml b/plugins/org.eclipse.emf.cdo.server.security/plugin.xml
index d514df05bf..37e91c84c1 100644
--- a/plugins/org.eclipse.emf.cdo.server.security/plugin.xml
+++ b/plugins/org.eclipse.emf.cdo.server.security/plugin.xml
@@ -27,6 +27,14 @@
type="annotation"
class="org.eclipse.emf.cdo.server.spi.security.SecurityManagerFactory$Annotation"/>
<factory
+ productGroup="org.eclipse.emf.cdo.server.security.commitHandlers"
+ type="annotation"
+ class="org.eclipse.emf.cdo.server.spi.security.AnnotationHandler$Factory"/>
+ <factory
+ productGroup="org.eclipse.emf.cdo.server.security.commitHandlers"
+ type="home"
+ class="org.eclipse.emf.cdo.server.spi.security.HomeFolderHandler$Factory"/>
+ <factory
productGroup="org.eclipse.emf.cdo.server.commands"
type="adduser"
class="org.eclipse.emf.cdo.server.internal.security.SecurityManagerCommand$AddUser"/>
diff --git a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java
index ea055ddbb3..3cce738e25 100644
--- a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java
+++ b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java
@@ -53,6 +53,7 @@ import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.net4j.Net4jUtil;
import org.eclipse.net4j.acceptor.IAcceptor;
import org.eclipse.net4j.connector.IConnector;
+import org.eclipse.net4j.util.ArrayUtil;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.container.IManagedContainer;
import org.eclipse.net4j.util.event.IListener;
@@ -65,11 +66,9 @@ import org.eclipse.net4j.util.security.IAuthenticator;
import org.eclipse.emf.common.util.EList;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
/**
@@ -79,8 +78,6 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
{
private static final Map<IRepository, InternalSecurityManager> SECURITY_MANAGERS = new HashMap<IRepository, InternalSecurityManager>();
- private static final String DEFAULT_HOME_FOLDER = "/home";
-
private final IListener repositoryListener = new LifecycleEventAdapter()
{
@Override
@@ -103,14 +100,18 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
private final IRepository.WriteAccessHandler writeAccessHandler = new WriteAccessHandler();
- private final List<CommitHandler> commitHandlers = new ArrayList<CommitHandler>();
-
private final String realmPath;
private final IManagedContainer container;
private final Map<String, User> users = Collections.synchronizedMap(new HashMap<String, User>());
+ private final Object commitHandlerLock = new Object();
+
+ private CommitHandler[] commitHandlers = {};
+
+ private CommitHandler2[] commitHandlers2 = {};
+
private InternalRepository repository;
private IAcceptor acceptor;
@@ -352,20 +353,24 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
public CommitHandler[] getCommitHandlers()
{
- synchronized (commitHandlers)
- {
- return commitHandlers.toArray(new CommitHandler[commitHandlers.size()]);
- }
+ return commitHandlers;
+ }
+
+ public CommitHandler2[] getCommitHandlers2()
+ {
+ return commitHandlers2;
}
public void addCommitHandler(CommitHandler handler)
{
checkInactive();
- synchronized (commitHandlers)
+ synchronized (commitHandlerLock)
{
- if (!commitHandlers.contains(handler))
+ commitHandlers = ArrayUtil.add(commitHandlers, handler);
+
+ if (handler instanceof CommitHandler2)
{
- commitHandlers.add(handler);
+ commitHandlers2 = ArrayUtil.add(commitHandlers2, (CommitHandler2)handler);
}
}
}
@@ -373,16 +378,24 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
public void removeCommitHandler(CommitHandler handler)
{
checkInactive();
- synchronized (commitHandlers)
+ synchronized (commitHandlerLock)
{
- commitHandlers.remove(handler);
+ commitHandlers = ArrayUtil.remove(commitHandlers, handler);
+
+ if (handler instanceof CommitHandler2)
+ {
+ commitHandlers2 = ArrayUtil.remove(commitHandlers2, (CommitHandler2)handler);
+ }
}
}
protected void initCommitHandlers(boolean firstTime)
{
- for (CommitHandler handler : getCommitHandlers())
+ CommitHandler[] handlers = getCommitHandlers();
+ for (int i = 0; i < handlers.length; i++)
{
+ CommitHandler handler = handlers[i];
+
try
{
handler.init(this, firstTime);
@@ -396,8 +409,11 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
protected void handleCommit(CommitContext commitContext, User user)
{
- for (CommitHandler handler : getCommitHandlers())
+ CommitHandler[] handlers = getCommitHandlers();
+ for (int i = 0; i < handlers.length; i++)
{
+ CommitHandler handler = handlers[i];
+
try
{
handler.handleCommit(this, commitContext, user);
@@ -409,6 +425,24 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
}
}
+ protected void handleCommitted(CommitContext commitContext)
+ {
+ CommitHandler2[] handlers = getCommitHandlers2();
+ for (int i = 0; i < handlers.length; i++)
+ {
+ CommitHandler2 handler = handlers[i];
+
+ try
+ {
+ handler.handleCommitted(this, commitContext);
+ }
+ catch (Exception ex)
+ {
+ OM.LOG.error(ex);
+ }
+ }
+ }
+
protected void init()
{
if (realm != null)
@@ -447,7 +481,6 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
boolean firstTime = !transaction.hasResource(realmPath);
if (firstTime)
{
- transaction.createResourceFolder(DEFAULT_HOME_FOLDER);
realm = createRealm();
CDOResource resource = transaction.createResource(realmPath);
@@ -462,8 +495,6 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
OM.LOG.info("Security realm loaded from " + realmPath);
}
- initCommitHandlers(firstTime);
-
try
{
transaction.commit();
@@ -486,6 +517,7 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
repository.addHandler(writeAccessHandler);
SECURITY_MANAGERS.put(repository, this);
+ initCommitHandlers(firstTime);
}
protected Realm createRealm()
@@ -514,18 +546,7 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
treeWriterRole.getPermissions().add(
factory.createFilterPermission(Access.WRITE, factory.createPackageFilter(EresourcePackage.eINSTANCE)));
- Role homeFolderOwnerRole = realm.addRole("Home Folder Owner");
- homeFolderOwnerRole.getPermissions().add(
- factory.createFilterPermission(Access.WRITE,
- factory.createResourceFilter(DEFAULT_HOME_FOLDER + "/${user}", Inclusion.EXACT_AND_DOWN)));
- homeFolderOwnerRole.getPermissions().add(
- factory.createFilterPermission(Access.READ,
- factory.createResourceFilter(DEFAULT_HOME_FOLDER, Inclusion.EXACT_AND_UP)));
-
Role adminRole = realm.addRole("Administration");
- adminRole.getPermissions().add(
- factory.createFilterPermission(Access.WRITE,
- factory.createResourceFilter(DEFAULT_HOME_FOLDER, Inclusion.EXACT_AND_UP)));
adminRole.getPermissions()
.add(
factory.createFilterPermission(Access.WRITE,
@@ -538,9 +559,6 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
Group adminsGroup = realm.addGroup("Administrators");
adminsGroup.getRoles().add(adminRole);
- Group usersGroup = realm.addGroup("Users");
- usersGroup.getRoles().add(homeFolderOwnerRole);
-
// Create users
User adminUser = realm.addUser("Administrator", "0000");
@@ -735,7 +753,9 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
{
if (transaction.getSessionID() == session.getSessionID())
{
- return; // Access through ISecurityManager.modify(RealmOperation)
+ // Access through ISecurityManager.modify(RealmOperation)
+ handleCommit(commitContext, null);
+ return;
}
CDOBranchPoint securityContext = commitContext.getBranchPoint();
@@ -754,7 +774,6 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
try
{
- // permissionRevisionsBeforeCommitting(commitContext, securityContext, user, commitContext.getNewObjects());
permissionRevisionsBeforeCommitting(commitContext, securityContext, user, commitContext.getDirtyObjects());
}
finally
@@ -777,12 +796,10 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage
}
}
- /**
- * @deprecated Not used.
- */
- @Deprecated
- public void handleTransactionAfterCommitted(ITransaction transaction, CommitContext commitContext, OMMonitor monitor)
+ public void handleTransactionAfterCommitted(ITransaction transaction, final CommitContext commitContext,
+ OMMonitor monitor)
{
+ handleCommitted(commitContext);
}
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/security/SecurityManagerUtil.java b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/security/SecurityManagerUtil.java
index 788f53cd78..23487ba420 100644
--- a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/security/SecurityManagerUtil.java
+++ b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/security/SecurityManagerUtil.java
@@ -12,6 +12,8 @@ package org.eclipse.emf.cdo.server.security;
import org.eclipse.emf.cdo.server.IRepository;
import org.eclipse.emf.cdo.server.internal.security.SecurityManager;
+import org.eclipse.emf.cdo.server.spi.security.AnnotationHandler;
+import org.eclipse.emf.cdo.server.spi.security.HomeFolderHandler;
import org.eclipse.emf.cdo.server.spi.security.SecurityManagerFactory;
import org.eclipse.net4j.util.container.IManagedContainer;
@@ -46,9 +48,12 @@ public final class SecurityManagerUtil
return new org.eclipse.emf.cdo.server.internal.security.SecurityManager(realmPath, container);
}
+ @SuppressWarnings("deprecation")
public static void prepareContainer(IManagedContainer container)
{
container.registerFactory(new SecurityManagerFactory.Default());
container.registerFactory(new SecurityManagerFactory.Annotation());
+ container.registerFactory(new AnnotationHandler.Factory());
+ container.registerFactory(new HomeFolderHandler.Factory());
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/AnnotationHandler.java b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/AnnotationHandler.java
index 853b1cc4c1..d86695d008 100644
--- a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/AnnotationHandler.java
+++ b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/AnnotationHandler.java
@@ -25,6 +25,9 @@ import org.eclipse.emf.cdo.security.SecurityPackage;
import org.eclipse.emf.cdo.security.User;
import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;
import org.eclipse.emf.cdo.server.security.ISecurityManager.RealmOperation;
+import org.eclipse.emf.cdo.server.spi.security.InternalSecurityManager.CommitHandler;
+
+import org.eclipse.net4j.util.factory.ProductCreationException;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
@@ -154,4 +157,22 @@ public class AnnotationHandler implements InternalSecurityManager.CommitHandler
}
}
}
+
+ /**
+ * @author Eike Stepper
+ * @since 4.3
+ */
+ public static class Factory extends InternalSecurityManager.CommitHandler.Factory
+ {
+ public Factory()
+ {
+ super("annotation");
+ }
+
+ @Override
+ public CommitHandler create(String description) throws ProductCreationException
+ {
+ return new AnnotationHandler();
+ }
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/HomeFolderHandler.java b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/HomeFolderHandler.java
new file mode 100644
index 0000000000..cff61f153a
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/HomeFolderHandler.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2012 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.spi.security;
+
+import org.eclipse.emf.cdo.security.Access;
+import org.eclipse.emf.cdo.security.Inclusion;
+import org.eclipse.emf.cdo.security.Realm;
+import org.eclipse.emf.cdo.security.Role;
+import org.eclipse.emf.cdo.security.SecurityFactory;
+import org.eclipse.emf.cdo.security.SecurityPackage;
+import org.eclipse.emf.cdo.security.User;
+import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;
+import org.eclipse.emf.cdo.server.internal.security.bundle.OM;
+import org.eclipse.emf.cdo.server.security.ISecurityManager.RealmOperation;
+import org.eclipse.emf.cdo.server.spi.security.InternalSecurityManager.CommitHandler;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.view.CDOView;
+
+import org.eclipse.net4j.util.factory.ProductCreationException;
+
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+
+import java.util.List;
+
+/**
+ * If the meaning of this type isn't clear, there really should be more of a description here...
+ *
+ * @author Eike Stepper
+ * @since 4.3
+ */
+public class HomeFolderHandler implements InternalSecurityManager.CommitHandler2
+{
+ public static final String DEFAULT_HOME_FOLDER = "/home";
+
+ private final String homeFolder;
+
+ public HomeFolderHandler(String homeFolder)
+ {
+ this.homeFolder = homeFolder == null || homeFolder.length() == 0 ? DEFAULT_HOME_FOLDER : homeFolder;
+ }
+
+ public HomeFolderHandler()
+ {
+ this(null);
+ }
+
+ public String getHomeFolder()
+ {
+ return homeFolder;
+ }
+
+ public void init(InternalSecurityManager securityManager, boolean firstTime)
+ {
+ if (firstTime)
+ {
+ EList<User> users = securityManager.getRealm().getAllUsers();
+ if (!users.isEmpty())
+ {
+ List<String> userIDs = new BasicEList<String>();
+ for (User user : users)
+ {
+ userIDs.add(user.getId());
+ }
+
+ handleUsers(securityManager, userIDs, true);
+ }
+ }
+ }
+
+ protected void initRole(Role role)
+ {
+ role.getPermissions().add(
+ SecurityFactory.eINSTANCE.createFilterPermission(Access.WRITE,
+ SecurityFactory.eINSTANCE.createResourceFilter(homeFolder + "/${user}", Inclusion.EXACT_AND_DOWN)));
+ role.getPermissions().add(
+ SecurityFactory.eINSTANCE.createFilterPermission(Access.READ,
+ SecurityFactory.eINSTANCE.createResourceFilter(homeFolder, Inclusion.EXACT_AND_UP)));
+ }
+
+ public void handleCommit(final InternalSecurityManager securityManager, CommitContext commitContext, User user)
+ {
+ // Do nothing
+ }
+
+ public void handleCommitted(final InternalSecurityManager securityManager, CommitContext commitContext)
+ {
+ List<String> userIDs = null;
+
+ InternalCDORevision[] newObjects = commitContext.getNewObjects();
+ for (int i = 0; i < newObjects.length; i++)
+ {
+ InternalCDORevision newObject = newObjects[i];
+ EClass eClass = newObject.getEClass();
+ if (eClass == SecurityPackage.Literals.USER)
+ {
+ String userID = (String)newObject.getValue(SecurityPackage.Literals.ASSIGNEE__ID);
+ if (userID != null)
+ {
+ if (userIDs == null)
+ {
+ userIDs = new BasicEList<String>();
+ }
+
+ userIDs.add(userID);
+ }
+ }
+ }
+
+ if (userIDs != null)
+ {
+ final List<String> list = userIDs;
+ long commitTime = commitContext.getBranchPoint().getTimeStamp();
+
+ CDOView view = securityManager.getRealm().cdoView();
+ view.runAfterUpdate(commitTime, new Runnable()
+ {
+ public void run()
+ {
+ handleUsers(securityManager, list, false);
+ }
+ });
+ }
+ }
+
+ protected void handleUsers(InternalSecurityManager securityManager, final List<String> userIDs, final boolean init)
+ {
+ securityManager.modify(new RealmOperation()
+ {
+ public void execute(Realm realm)
+ {
+ String roleID = "Home Folder " + homeFolder;
+ Role role;
+
+ if (init)
+ {
+ role = realm.addRole(roleID);
+ initRole(role);
+ }
+ else
+ {
+ role = realm.getRole(roleID);
+ if (role == null)
+ {
+ OM.LOG.warn("Role '" + roleID + "' not found in " + HomeFolderHandler.this);
+ return;
+ }
+ }
+
+ CDOTransaction transaction = (CDOTransaction)realm.cdoView();
+
+ for (String userID : userIDs)
+ {
+ try
+ {
+ User user = realm.getUser(userID);
+ if (user == null)
+ {
+ OM.LOG.warn("User '" + userID + "' not found in " + HomeFolderHandler.this);
+ }
+ else
+ {
+ handleUser(transaction, realm, role, user);
+ }
+ }
+ catch (Exception ex)
+ {
+ OM.LOG.error(ex);
+ }
+ }
+ }
+ });
+ }
+
+ protected void handleUser(CDOTransaction transaction, Realm realm, Role role, User user) throws Exception
+ {
+ user.getRoles().add(role);
+ transaction.createResourceFolder(getHomeFolder() + "/" + user.getId());
+ }
+
+ @Override
+ public String toString()
+ {
+ return getClass().getSimpleName() + "[" + homeFolder + "]";
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class Factory extends InternalSecurityManager.CommitHandler.Factory
+ {
+ public Factory()
+ {
+ super("home");
+ }
+
+ @Override
+ public CommitHandler create(String homeFolder) throws ProductCreationException
+ {
+ return new HomeFolderHandler(homeFolder);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/InternalSecurityManager.java b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/InternalSecurityManager.java
index 77963344ee..807c7fd1c3 100644
--- a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/InternalSecurityManager.java
+++ b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/InternalSecurityManager.java
@@ -16,6 +16,7 @@ import org.eclipse.emf.cdo.server.security.ISecurityManager;
import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.net4j.util.container.IManagedContainer;
+import org.eclipse.net4j.util.factory.ProductCreationException;
/**
* If the meaning of this type isn't clear, there really should be more of a description here...
@@ -34,6 +35,11 @@ public interface InternalSecurityManager extends ISecurityManager
public CommitHandler[] getCommitHandlers();
+ /**
+ * @since 4.3
+ */
+ public CommitHandler2[] getCommitHandlers2();
+
public void addCommitHandler(CommitHandler handler);
public void removeCommitHandler(CommitHandler handler);
@@ -47,6 +53,66 @@ public interface InternalSecurityManager extends ISecurityManager
{
public void init(InternalSecurityManager securityManager, boolean firstTime);
+ /**
+ * Called <b>before</b> the commit is security checked and passed to the repository.
+ *
+ * @param user the committing user or <code>null</code> if this commit is
+ * {@link ISecurityManager#modify(ISecurityManager.RealmOperation, boolean) triggered} by the system.
+ *
+ * @see CommitHandler2
+ */
public void handleCommit(InternalSecurityManager securityManager, CommitContext commitContext, User user);
+
+ /**
+ * Creates {@link CommitHandler} instances.
+ *
+ * @author Eike Stepper
+ * @since 4.3
+ */
+ public static abstract class Factory extends org.eclipse.net4j.util.factory.Factory
+ {
+ public static final String PRODUCT_GROUP = "org.eclipse.emf.cdo.server.security.commitHandlers";
+
+ public Factory(String type)
+ {
+ super(PRODUCT_GROUP, type);
+ }
+
+ public abstract CommitHandler create(String description) throws ProductCreationException;
+ }
+ }
+
+ /**
+ * If the meaning of this type isn't clear, there really should be more of a description here...
+ *
+ * @author Eike Stepper
+ * @since 4.3
+ */
+ public interface CommitHandler2 extends CommitHandler
+ {
+ /**
+ * Called <b>after</b> the commit has succeeded.
+ */
+ public void handleCommitted(InternalSecurityManager securityManager, CommitContext commitContext);
+
+ /**
+ * @author Eike Stepper
+ */
+ public static abstract class WithUser implements CommitHandler2
+ {
+ public void handleCommit(InternalSecurityManager securityManager, CommitContext commitContext, User user)
+ {
+ commitContext.setData(this, user);
+ }
+
+ public void handleCommitted(InternalSecurityManager securityManager, CommitContext commitContext)
+ {
+ User user = commitContext.getData(this);
+ handleCommitted(securityManager, commitContext, user);
+ }
+
+ protected abstract void handleCommitted(InternalSecurityManager securityManager, CommitContext commitContext,
+ User user);
+ }
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/SecurityManagerFactory.java b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/SecurityManagerFactory.java
index d07142f165..4f337735dc 100644
--- a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/SecurityManagerFactory.java
+++ b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/spi/security/SecurityManagerFactory.java
@@ -10,12 +10,19 @@
*/
package org.eclipse.emf.cdo.server.spi.security;
+import org.eclipse.emf.cdo.server.internal.security.bundle.OM;
import org.eclipse.emf.cdo.server.security.ISecurityManager;
import org.eclipse.emf.cdo.server.security.SecurityManagerUtil;
+import org.eclipse.emf.cdo.server.spi.security.InternalSecurityManager.CommitHandler;
+import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.container.IManagedContainer;
+import org.eclipse.net4j.util.container.IManagedContainer.ContainerAware;
import org.eclipse.net4j.util.factory.Factory;
import org.eclipse.net4j.util.factory.ProductCreationException;
+import java.util.List;
+
/**
* If the meaning of this type isn't clear, there really should be more of a description here...
*
@@ -37,19 +44,64 @@ public abstract class SecurityManagerFactory extends Factory
*
* @author Eike Stepper
*/
- public static class Default extends SecurityManagerFactory
+ public static class Default extends SecurityManagerFactory implements ContainerAware
{
private static final String TYPE = "default";
+ private IManagedContainer container;
+
public Default()
{
super(TYPE);
}
+ /**
+ * @since 4.3
+ */
+ public void setManagedContainer(IManagedContainer container)
+ {
+ this.container = container;
+ }
+
@Override
- public ISecurityManager create(String realmPath) throws ProductCreationException
+ public ISecurityManager create(String description) throws ProductCreationException
+ {
+ List<String> tokens = StringUtil.split(description, ":", "()");
+ String realmPath = tokens.get(0);
+
+ ISecurityManager securityManager = SecurityManagerUtil.createSecurityManager(realmPath);
+
+ for (int i = 1; i < tokens.size(); i++)
+ {
+ String token = tokens.get(i);
+ CommitHandler handler = getHandler(container, token);
+ ((InternalSecurityManager)securityManager).addCommitHandler(handler);
+ }
+
+ return securityManager;
+ }
+
+ /**
+ * @since 4.3
+ */
+ protected CommitHandler getHandler(IManagedContainer container, String token)
{
- return SecurityManagerUtil.createSecurityManager(realmPath);
+ String factoryType;
+ String description;
+
+ int pos = token.indexOf('(');
+ if (pos == -1)
+ {
+ factoryType = token.trim();
+ description = null;
+ }
+ else
+ {
+ factoryType = token.substring(0, pos).trim();
+ description = token.substring(pos + 1, token.length() - 1).trim();
+ }
+
+ return (CommitHandler)container.getElement(CommitHandler.Factory.PRODUCT_GROUP, factoryType, description);
}
}
@@ -57,7 +109,9 @@ public abstract class SecurityManagerFactory extends Factory
* If the meaning of this type isn't clear, there really should be more of a description here...
*
* @author Eike Stepper
+ * @deprecated As of 4.3 use {@link Default} with a description like "realmPath<b>:annotation</b>".
*/
+ @Deprecated
public static class Annotation extends SecurityManagerFactory
{
private static final String TYPE = "annotation";
@@ -70,6 +124,9 @@ public abstract class SecurityManagerFactory extends Factory
@Override
public ISecurityManager create(String realmPath) throws ProductCreationException
{
+ OM.LOG
+ .warn("SecurityManagerFactory.Annotation is deprecated. As of 4.3 use SecurityManagerFactory.Default with a description like \"realmPath:annotation\"");
+
InternalSecurityManager securityManager = (InternalSecurityManager)SecurityManagerUtil
.createSecurityManager(realmPath);
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java
index efac9096a8..3985e6dbf8 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java
@@ -184,6 +184,8 @@ public class TransactionCommitContext implements InternalCommitContext
private ExtendedDataInputStream lobs;
+ private Map<Object, Object> data;
+
public TransactionCommitContext(InternalTransaction transaction)
{
this.transaction = transaction;
@@ -544,6 +546,30 @@ public class TransactionCommitContext implements InternalCommitContext
lobs = in;
}
+ public <T> T getData(Object key)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ T result = (T)data.get(key);
+ return result;
+ }
+
+ public synchronized <T extends Object> T setData(Object key, T value)
+ {
+ if (data == null)
+ {
+ data = new HashMap<Object, Object>();
+ }
+
+ @SuppressWarnings("unchecked")
+ T old = (T)data.put(key, value);
+ return old;
+ }
+
private InternalCDOPackageUnit[] lockPackageRegistry(InternalCDOPackageUnit[] packageUnits)
throws InterruptedException
{
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java
index 4ae413fc9c..e28716723a 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java
@@ -444,6 +444,16 @@ public interface IStoreAccessor extends IQueryHandlerProvider, BranchLoader, Com
* @since 4.1
*/
public List<LockState<Object, IView>> getPostCommmitLockStates();
+
+ /**
+ * @since 4.3
+ */
+ public <T> T getData(Object key);
+
+ /**
+ * @since 4.3
+ */
+ public <T> T setData(Object key, T data);
}
/**
diff --git a/plugins/org.eclipse.net4j.util/.settings/.api_filters b/plugins/org.eclipse.net4j.util/.settings/.api_filters
index af1f432d4e..ea95b5f2b1 100644
--- a/plugins/org.eclipse.net4j.util/.settings/.api_filters
+++ b/plugins/org.eclipse.net4j.util/.settings/.api_filters
@@ -68,4 +68,13 @@
</message_arguments>
</filter>
</resource>
+ <resource path="src/org/eclipse/net4j/util/container/IManagedContainerFactory.java" type="org.eclipse.net4j.util.container.IManagedContainerFactory">
+ <filter comment="https://bugs.eclipse.org/bugs/show_bug.cgi?id=404845" id="403984517">
+ <message_arguments>
+ <message_argument value="org.eclipse.net4j.util.container.IManagedContainerFactory"/>
+ <message_argument value="org.eclipse.net4j.util.container.IManagedContainer$ContainerAware"/>
+ <message_argument value="setManagedContainer(IManagedContainer)"/>
+ </message_arguments>
+ </filter>
+ </resource>
</component>
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ArrayUtil.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ArrayUtil.java
new file mode 100644
index 0000000000..6d7dcaef0c
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ArrayUtil.java
@@ -0,0 +1,77 @@
+package org.eclipse.net4j.util;
+
+import java.lang.reflect.Array;
+
+/**
+ * Various static helper methods.
+ *
+ * @author Eike Stepper
+ * @since 3.4
+ */
+public final class ArrayUtil
+{
+ private ArrayUtil()
+ {
+ }
+
+ public static <T> T[] add(T[] array, T element)
+ {
+ int length = array.length;
+
+ @SuppressWarnings("unchecked")
+ T[] newArray = (T[])Array.newInstance(array.getClass().getComponentType(), length + 1);
+
+ System.arraycopy(array, 0, newArray, 0, length);
+ newArray[length] = element;
+ return newArray;
+ }
+
+ public static <T> T[] remove(T[] array, T element)
+ {
+ int length = array.length;
+ for (int i = 0; i < array.length; i++)
+ {
+ T t = array[i];
+ if (ObjectUtil.equals(t, element))
+ {
+ @SuppressWarnings("unchecked")
+ T[] newArray = (T[])Array.newInstance(array.getClass().getComponentType(), length - 1);
+
+ if (i != 0)
+ {
+ System.arraycopy(array, 0, newArray, 0, i);
+ }
+
+ int next = i + 1;
+ if (next <= length)
+ {
+ System.arraycopy(array, next, newArray, i, length - next);
+ }
+
+ return newArray;
+ }
+ }
+
+ return array;
+ }
+
+ public static String toString(Object[] array)
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append('{');
+
+ for (int i = 0; i < array.length; i++)
+ {
+ Object element = array[i];
+ if (i != 0)
+ {
+ builder.append(", ");
+ }
+
+ builder.append(element);
+ }
+
+ builder.append('}');
+ return builder.toString();
+ }
+}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/StringUtil.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/StringUtil.java
index 90202d5de6..eb31c81cc5 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/StringUtil.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/StringUtil.java
@@ -14,7 +14,9 @@ import org.eclipse.net4j.util.om.OMPlatform;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* Various static helper methods for dealing with strings.
@@ -73,6 +75,54 @@ public final class StringUtil
return text;
}
+ /**
+ * @since 3.4
+ */
+ public static List<String> split(String text, String separators, String brackets)
+ {
+ List<String> result = new ArrayList<String>();
+
+ StringBuilder builder = new StringBuilder();
+ int length = text.length();
+ int bracketLevel = 0;
+
+ for (int i = 0; i < length; i++)
+ {
+ char c = text.charAt(i);
+
+ if (bracketLevel == 0 && separators.indexOf(c) != -1)
+ {
+ result.add(builder.toString());
+ builder.setLength(0);
+ }
+ else
+ {
+ builder.append(c);
+ }
+
+ if (brackets != null)
+ {
+ int bracket = brackets.indexOf(c);
+ if (bracket != -1)
+ {
+ if ((bracket & 1) == 0)
+ {
+ // Opening bracket
+ ++bracketLevel;
+ }
+ else
+ {
+ // Closing bracket
+ --bracketLevel;
+ }
+ }
+ }
+ }
+
+ result.add(builder.toString());
+ return result;
+ }
+
public static String safe(String str)
{
if (str == null)
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IManagedContainer.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IManagedContainer.java
index 25b0e138cb..6695c5b4e1 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IManagedContainer.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IManagedContainer.java
@@ -77,4 +77,18 @@ public interface IManagedContainer extends IContainer<Object>, ILifecycle
public void loadElements(InputStream stream) throws IOException, FactoryNotFoundException, ProductCreationException;
public void saveElements(OutputStream stream) throws IOException;
+
+ /**
+ * @author Eike Stepper
+ * @since 3.4
+ */
+ public interface ContainerAware
+ {
+ /**
+ * Assigns the container that I should use to get my dependencies.
+ *
+ * @param container the container in which I am created/registered
+ */
+ public void setManagedContainer(IManagedContainer container);
+ }
}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IManagedContainerFactory.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IManagedContainerFactory.java
index d97c681668..0cc4d6f8ac 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IManagedContainerFactory.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IManagedContainerFactory.java
@@ -10,6 +10,7 @@
*/
package org.eclipse.net4j.util.container;
+import org.eclipse.net4j.util.container.IManagedContainer.ContainerAware;
import org.eclipse.net4j.util.factory.IFactory;
/**
@@ -17,19 +18,14 @@ import org.eclipse.net4j.util.factory.IFactory;
* awareness of the container that instantiated it, so that the
* factory may reach back into that container for dependencies.
*
+ * @author Christian W. Damus (CEA)
+ * @author Eike Stepper
* @since 3.3
*/
-public interface IManagedContainerFactory extends IFactory
+public interface IManagedContainerFactory extends IFactory, ContainerAware
{
/**
* Obtains the container that I should use to get my dependencies.
*/
public IManagedContainer getManagedContainer();
-
- /**
- * Assigns the container that I should use to get my dependencies.
- *
- * @param container the container in which I am created/registered
- */
- public void setManagedContainer(IManagedContainer container);
}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/ManagedContainer.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/ManagedContainer.java
index 8379cceb09..4ef445dabb 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/ManagedContainer.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/ManagedContainer.java
@@ -109,9 +109,9 @@ public class ManagedContainer extends Lifecycle implements IManagedContainer
private void updateFactory(Map.Entry<IFactoryKey, IFactory> entry, IManagedContainer container)
{
IFactory factory = entry.getValue();
- if (factory instanceof IManagedContainerFactory)
+ if (factory instanceof ContainerAware)
{
- IManagedContainerFactory f = (IManagedContainerFactory)factory;
+ ContainerAware f = (ContainerAware)factory;
f.setManagedContainer(container);
}
}
@@ -377,6 +377,11 @@ public class ManagedContainer extends Lifecycle implements IManagedContainer
if (oldElement != element)
{
+ if (element instanceof ContainerAware)
+ {
+ ((ContainerAware)element).setManagedContainer(this);
+ }
+
EventUtil.addUniqueListener(element, elementListener);
if (oldElement != null)
@@ -411,6 +416,11 @@ public class ManagedContainer extends Lifecycle implements IManagedContainer
{
EventUtil.removeListener(element, elementListener);
fireEvent(new SingleDeltaContainerEvent<Object>(this, element, IContainerDelta.Kind.REMOVED));
+
+ if (element instanceof ContainerAware)
+ {
+ ((ContainerAware)element).setManagedContainer(null);
+ }
}
return element;

Back to the top