diff options
author | Eike Stepper | 2013-09-20 10:50:20 +0000 |
---|---|---|
committer | Eike Stepper | 2013-09-20 10:50:20 +0000 |
commit | 6e4718788e24cefc9c06f0e73fba75858da6f2d0 (patch) | |
tree | 47bdd7fbd228b0d465499eac5e47122f06b7790d /plugins | |
parent | 3faadda34ad1992cd06a5c8b74ba3c1c01568299 (diff) | |
download | cdo-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
Diffstat (limited to 'plugins')
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; |