diff options
24 files changed, 546 insertions, 57 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common.db/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.common.db/META-INF/MANIFEST.MF index 45c30cb5c0..93a8721010 100644 --- a/plugins/org.eclipse.emf.cdo.common.db/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.cdo.common.db/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.emf.cdo.common.db;singleton:=true -Bundle-Version: 3.0.300.qualifier +Bundle-Version: 3.0.400.qualifier Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -13,7 +13,7 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)";resoluti org.eclipse.emf.cdo.common;bundle-version="[4.0.0,5.0.0)";visibility:=reexport, org.eclipse.net4j.db;bundle-version="[4.0.0,5.0.0)" Import-Package: org.osgi.framework;version="[1.3.0,2.0.0)";resolution:=optional -Export-Package: org.eclipse.emf.cdo.common.db;version="3.0.300", - org.eclipse.emf.cdo.common.internal.db;version="3.0.300";x-friends:="org.eclipse.emf.cdo.tests.db", - org.eclipse.emf.cdo.common.internal.db.bundle;version="3.0.300";x-internal:=true, - org.eclipse.emf.cdo.common.internal.db.cache;version="3.0.300";x-friends:="org.eclipse.emf.cdo.tests.db" +Export-Package: org.eclipse.emf.cdo.common.db;version="3.0.400", + org.eclipse.emf.cdo.common.internal.db;version="3.0.400";x-friends:="org.eclipse.emf.cdo.tests.db", + org.eclipse.emf.cdo.common.internal.db.bundle;version="3.0.400";x-internal:=true, + org.eclipse.emf.cdo.common.internal.db.cache;version="3.0.400";x-friends:="org.eclipse.emf.cdo.tests.db" diff --git a/plugins/org.eclipse.emf.cdo.common.db/src/org/eclipse/emf/cdo/common/internal/db/cache/DBRevisionCache.java b/plugins/org.eclipse.emf.cdo.common.db/src/org/eclipse/emf/cdo/common/internal/db/cache/DBRevisionCache.java index 3ef2f2e424..47cbe5ac7d 100644 --- a/plugins/org.eclipse.emf.cdo.common.db/src/org/eclipse/emf/cdo/common/internal/db/cache/DBRevisionCache.java +++ b/plugins/org.eclipse.emf.cdo.common.db/src/org/eclipse/emf/cdo/common/internal/db/cache/DBRevisionCache.java @@ -416,6 +416,12 @@ public class DBRevisionCache extends Lifecycle implements InternalCDORevisionCac } } + public void getAllRevisions(List<InternalCDORevision> result) + { + // TODO: implement DBRevisionCache.enclosing_method(enclosing_method_arguments) + throw new UnsupportedOperationException(); + } + /** * Adds a given revision to this cache. It furthermore updates the revised timestamp of the latest (before inserting * the new one) revision diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java index 15b8b8977d..2d9416ce50 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java @@ -252,6 +252,11 @@ public interface CDOProtocolConstants */ public static final short SIGNAL_SET_LOCK_NOTIFICATION_MODE = 54; + /** + * @since 4.3 + */ + public static final short SIGNAL_LOAD_PERMISSIONS = 55; + // ////////////////////////////////////////////////////////////////////// // Session Refresh diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/CDOPermission.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/CDOPermission.java index b07a76d2e5..38b876df75 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/CDOPermission.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/CDOPermission.java @@ -50,6 +50,8 @@ public enum CDOPermission public static CDOPermission get(int bits) { + bits &= WRITE.getBits(); + switch (bits) { case 0x00: diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheAuditing.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheAuditing.java index 6a0a710111..cb050558d2 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheAuditing.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheAuditing.java @@ -132,6 +132,17 @@ public class CDORevisionCacheAuditing extends AbstractCDORevisionCache return result; } + public void getAllRevisions(List<InternalCDORevision> result) + { + synchronized (revisionLists) + { + for (RevisionList list : revisionLists.values()) + { + list.getAllRevisions(result); + } + } + } + public List<CDORevision> getRevisions(CDOBranchPoint branchPoint) { CDOBranch branch = branchPoint.getBranch(); @@ -143,7 +154,6 @@ public class CDORevisionCacheAuditing extends AbstractCDORevisionCache for (Map.Entry<Object, RevisionList> entry : revisionLists.entrySet()) { if (isKeyInBranch(entry.getKey(), branch)) - // if (ObjectUtil.equals(entry.getKey().getBranch(), branch)) { RevisionList list = entry.getValue(); InternalCDORevision revision = list.getRevision(branchPoint.getTimeStamp()); @@ -443,5 +453,18 @@ public class CDORevisionCacheAuditing extends AbstractCDORevisionCache } } } + + public void getAllRevisions(List<InternalCDORevision> result) + { + for (Iterator<Reference<InternalCDORevision>> it = iterator(); it.hasNext();) + { + Reference<InternalCDORevision> ref = it.next(); + InternalCDORevision revision = ref.get(); + if (revision != null) + { + result.add(revision); + } + } + } } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheNonAuditing.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheNonAuditing.java index d8a505508f..8d27d1c95e 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheNonAuditing.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheNonAuditing.java @@ -147,6 +147,18 @@ public class CDORevisionCacheNonAuditing extends AbstractCDORevisionCache return result; } + public void getAllRevisions(List<InternalCDORevision> result) + { + for (Reference<InternalCDORevision> ref : revisions.values()) + { + InternalCDORevision revision = ref.get(); + if (revision != null) + { + result.add(revision); + } + } + } + public List<CDORevision> getRevisions(CDOBranchPoint branchPoint) { checkBranch(branchPoint.getBranch()); diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java index 1e61b49dda..c1a15ce0e6 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java @@ -39,10 +39,10 @@ public class CDORevisionImpl extends BaseCDORevision protected CDORevisionImpl(CDORevisionImpl source) { super(source); + boolean bypassPermissionChecks = bypassPermissionChecks(true); try { - bypassPermissionChecks(true); EStructuralFeature[] features = clearValues(); int length = features.length; @@ -67,7 +67,7 @@ public class CDORevisionImpl extends BaseCDORevision } finally { - bypassPermissionChecks(false); + bypassPermissionChecks(bypassPermissionChecks); } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/NOOPRevisionCache.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/NOOPRevisionCache.java index 12af0d6230..3b71507bb9 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/NOOPRevisionCache.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/NOOPRevisionCache.java @@ -94,6 +94,11 @@ public class NOOPRevisionCache extends Lifecycle implements InternalCDORevisionC return Collections.emptyMap(); } + public void getAllRevisions(List<InternalCDORevision> result) + { + // Do nothing + } + public List<CDORevision> getRevisions(CDOBranchPoint branchPoint) { return Collections.emptyList(); diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java index c6c07e2c29..954af9957c 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java @@ -861,14 +861,15 @@ public abstract class BaseCDORevision extends AbstractCDORevision synchronized (this) { + boolean bypassPermissionChecks = bypassPermissionChecks(true); + try { - bypassPermissionChecks(true); setValue(featureIndex, list); } finally { - bypassPermissionChecks(false); + bypassPermissionChecks(bypassPermissionChecks); } } } @@ -1156,6 +1157,16 @@ public abstract class BaseCDORevision extends AbstractCDORevision builder.append("WRITE"); } + if ((flags & BYPASS_PERMISSION_CHECKS_FLAG) != 0) + { + if (builder.length() != 0) + { + builder.append("|"); + } + + builder.append("BYPASS_PERMISSION_CHECKS"); + } + return builder.toString(); } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionCache.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionCache.java index 101c2bcd95..c773b74966 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionCache.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionCache.java @@ -38,4 +38,12 @@ public interface InternalCDORevisionCache extends CDORevisionCache, CDOAllRevisi public void clear(); public List<CDORevision> getRevisions(CDOBranchPoint branchPoint); + + /** + * Fills a list with all {@link CDORevision revisions}. + * + * @since 4.3 + * @see #getAllRevisions() + */ + public void getAllRevisions(List<InternalCDORevision> result); } diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java index ee560a9e04..5be8ba2757 100644 --- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java @@ -30,6 +30,7 @@ import org.eclipse.emf.cdo.common.model.CDOPackageUnit; import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; import org.eclipse.emf.cdo.common.revision.CDORevisionKey; +import org.eclipse.emf.cdo.common.security.CDOPermission; import org.eclipse.emf.cdo.common.util.TransportException; import org.eclipse.emf.cdo.internal.net4j.bundle.OM; import org.eclipse.emf.cdo.session.CDOSession; @@ -553,4 +554,9 @@ public class CDOClientProtocol extends SignalProtocol<CDOSession> implements CDO { send(new SetLockNotificationModeRequest(this, mode)); } + + public Map<InternalCDORevision, CDOPermission> loadPermissions(InternalCDORevision[] revisions) + { + return send(new LoadPermissionsRequest(this, revisions)); + } } diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LoadPermissionsRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LoadPermissionsRequest.java new file mode 100644 index 0000000000..ec6479c795 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LoadPermissionsRequest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2011, 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.internal.net4j.protocol; + +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.protocol.CDODataInput; +import org.eclipse.emf.cdo.common.protocol.CDODataOutput; +import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; +import org.eclipse.emf.cdo.common.security.CDOPermission; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Eike Stepper + */ +public class LoadPermissionsRequest extends CDOClientRequest<Map<InternalCDORevision, CDOPermission>> +{ + private InternalCDORevision[] revisions; + + public LoadPermissionsRequest(CDOClientProtocol protocol, InternalCDORevision[] revisions) + { + super(protocol, CDOProtocolConstants.SIGNAL_LOAD_PERMISSIONS); + this.revisions = revisions; + } + + @Override + protected void requesting(CDODataOutput out) throws IOException + { + int length = revisions.length; + out.writeInt(length); + + for (int i = 0; i < length; i++) + { + InternalCDORevision revision = revisions[i]; + CDOID id = revision.getID(); + out.writeCDOID(id); + + byte bits = revision.getPermission().getBits(); + out.writeByte(bits); + } + + int referenceChunk = getSession().options().getCollectionLoadingPolicy().getInitialChunkSize(); + out.writeInt(referenceChunk); + } + + @Override + protected Map<InternalCDORevision, CDOPermission> confirming(CDODataInput in) throws IOException + { + Map<InternalCDORevision, CDOPermission> oldPermissions = new HashMap<InternalCDORevision, CDOPermission>(); + + int length = revisions.length; + for (int i = 0; i < length; i++) + { + InternalCDORevision revision = revisions[i]; + CDOPermission oldPermission = revision.getPermission(); + + byte bits = in.readByte(); + CDOPermission newPermission = CDOPermission.get(bits); + + if (oldPermission != newPermission) + { + boolean bypassPermissionChecks = revision.bypassPermissionChecks(true); + + try + { + if (oldPermission == CDOPermission.NONE) + { + revision.readValues(in); + } + else if (newPermission == CDOPermission.NONE) + { + revision.clearValues(); + } + } + finally + { + revision.bypassPermissionChecks(bypassPermissionChecks); + } + + revision.setPermission(newPermission); + oldPermissions.put(revision, oldPermission); + } + } + + return oldPermissions; + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java index 0da248e629..6708c5e9ce 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java @@ -348,6 +348,9 @@ public class CDOServerProtocol extends SignalProtocol<InternalSession> implement case SIGNAL_SET_LOCK_NOTIFICATION_MODE: return new SetLockNotificationModeIndication(this); + case SIGNAL_LOAD_PERMISSIONS: + return new LoadPermissionsIndication(this); + default: return super.createSignalReactor(signalID); } diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LoadPermissionsIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LoadPermissionsIndication.java new file mode 100644 index 0000000000..b81b06a86e --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LoadPermissionsIndication.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2011, 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: + * Caspar De Groot - initial API and implementation + */ +package org.eclipse.emf.cdo.server.internal.net4j.protocol; + +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.protocol.CDODataInput; +import org.eclipse.emf.cdo.common.protocol.CDODataOutput; +import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.security.CDOPermission; +import org.eclipse.emf.cdo.server.IPermissionManager; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; +import org.eclipse.emf.cdo.spi.server.InternalRepository; +import org.eclipse.emf.cdo.spi.server.InternalSession; + +import java.io.IOException; + +/** + * @author Caspar De Groot + */ +public class LoadPermissionsIndication extends CDOServerReadIndication +{ + private CDOID[] ids; + + private CDOPermission[] oldPermissions; + + private int referenceChunk; + + public LoadPermissionsIndication(CDOServerProtocol protocol) + { + super(protocol, CDOProtocolConstants.SIGNAL_LOAD_PERMISSIONS); + } + + @Override + protected void indicating(CDODataInput in) throws IOException + { + int length = in.readInt(); + ids = new CDOID[length]; + oldPermissions = new CDOPermission[length]; + + for (int i = 0; i < length; i++) + { + ids[i] = in.readCDOID(); + oldPermissions[i] = CDOPermission.get(in.readByte()); + } + + referenceChunk = in.readInt(); + } + + @Override + protected void responding(CDODataOutput out) throws IOException + { + InternalSession session = getSession(); + InternalRepository repository = getRepository(); + InternalCDORevisionManager revisionManager = repository.getRevisionManager(); + IPermissionManager permissionManager = repository.getSessionManager().getPermissionManager(); + CDOBranchPoint head = repository.getBranchManager().getMainBranch().getHead(); + + int length = ids.length; + for (int i = 0; i < length; i++) + { + CDOID id = ids[i]; + CDOPermission oldPermission = oldPermissions[i]; + + InternalCDORevision revision = revisionManager.getRevision(id, head, 0, CDORevision.DEPTH_NONE, true); + + CDOPermission newPermission = permissionManager.getPermission(revision, head, session); + out.writeByte(newPermission.getBits()); + + if (oldPermission == CDOPermission.NONE && newPermission != CDOPermission.NONE) + { + revision.writeValues(out, referenceChunk); + } + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java index f63f2df556..a2f70b3867 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java @@ -31,6 +31,7 @@ import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator; import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; import org.eclipse.emf.cdo.common.revision.CDORevisionKey; +import org.eclipse.emf.cdo.common.security.CDOPermission; import org.eclipse.emf.cdo.common.util.CDOQueryQueue; import org.eclipse.emf.cdo.server.StoreThreadLocal; import org.eclipse.emf.cdo.session.remote.CDORemoteSession; @@ -559,6 +560,11 @@ public class EmbeddedClientSessionProtocol extends Lifecycle implements CDOSessi throw new UnsupportedOperationException(); } + public Map<InternalCDORevision, CDOPermission> loadPermissions(InternalCDORevision[] revisions) + { + throw new UnsupportedOperationException(); + } + public CDOAuthenticationResult handleAuthenticationChallenge(byte[] randomToken) throws Exception { CDOAuthenticator authenticator = getSession().getAuthenticator(); diff --git a/plugins/org.eclipse.emf.cdo.tests/launches/CDO AllTests (MEM branching UUIDs).launch b/plugins/org.eclipse.emf.cdo.tests/launches/CDO AllTests (MEM branching UUIDs).launch index eea9442329..3aa6b5bce9 100644 --- a/plugins/org.eclipse.emf.cdo.tests/launches/CDO AllTests (MEM branching UUIDs).launch +++ b/plugins/org.eclipse.emf.cdo.tests/launches/CDO AllTests (MEM branching UUIDs).launch @@ -12,5 +12,5 @@ <stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.emf.cdo.tests.AllTestsMEMBranchesUUIDs"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.emf.cdo.tests"/> -<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms40m -Xmx1024m -Dorg.eclipse.net4j.util.om.trace.disable=true"/> +<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms40m -Xmx1g -Dorg.eclipse.net4j.util.om.trace.disable=true -Dorg.eclipse.emf.cdo.tests.config.impl.RepositoryConfig.enableServerBrowser=false"/> </launchConfiguration> diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_418267_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_418267_Test.java index 341496768a..8f209c9a64 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_418267_Test.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_418267_Test.java @@ -34,6 +34,8 @@ import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.net4j.util.security.IPasswordCredentials; import org.eclipse.net4j.util.security.PasswordCredentials; +import org.eclipse.emf.ecore.EObject; + /** * Bug 418267 - [Security] Cached permissions are not always properly updated after commits. * @@ -136,61 +138,77 @@ public class Bugzilla_418267_Test extends AbstractCDOTest User writer = realm.addUser(CREDENTIALS_WRITER); writer.getRoles().add(realm.getRole(Role.ALL_OBJECTS_WRITER)); } - - private Access getAccess(CDOPermission permission) - { - switch (permission) - { - case READ: - return Access.READ; - - case WRITE: - return Access.WRITE; - - default: - return null; - } - } }); CDOSession sessionWriter = openSession(CREDENTIALS_WRITER); CDOTransaction transactionWriter = sessionWriter.openTransaction(); CDOResource resourceWriter = transactionWriter.getResource(pathResource1); + Company companyWriter = (Company)resourceWriter.getContents().get(0); CDOResourceFolder targetFolderWriter = transactionWriter.getResourceFolder(pathFolder2); CDOSession session = openSession(CREDENTIALS); session.options().setPassiveUpdateMode(PassiveUpdateMode.ADDITIONS); CDOTransaction transaction = session.openTransaction(); - assertPermission(from, resourceWriter, transaction); // Pre check + assertPermissions(from, transaction, resourceWriter, companyWriter); // Pre check targetFolderWriter.getNodes().add(resourceWriter); // Move + + // int xxx; + // transactionWriter.commit(); + // sleep(1000000000); + commitAndSync(transactionWriter, transaction); // Commit + invalidate - assertPermission(to, resourceWriter, transaction); // Post check + assertPermissions(to, transaction, resourceWriter, companyWriter); // Post check } - private static void assertPermission(CDOPermission expected, CDOResource resourceWriter, CDOTransaction transaction) + private static Access getAccess(CDOPermission permission) { - if (expected == CDOPermission.NONE) + switch (permission) { - try - { - transaction.getObject(resourceWriter); - fail("Exception expected"); - } - catch (Exception ex) - { - // SUCCESS - } + case READ: + return Access.READ; + + case WRITE: + return Access.WRITE; + + default: + return null; } - else - { - CDOResource resource = transaction.getObject(resourceWriter); - assertEquals(expected, resource.cdoPermission()); + } - Company company = (Company)resource.getContents().get(0); - assertEquals(expected, CDOUtil.getCDOObject(company).cdoPermission()); + private static void assertPermissions(CDOPermission expected, CDOTransaction transaction, EObject... objectsWriter) + { + for (EObject objectWriter : objectsWriter) + { + EObject object = transaction.getObject(objectWriter); + CDOPermission permission = CDOUtil.getCDOObject(object).cdoPermission(); + assertEquals(expected, permission); } + + // if (expected == CDOPermission.NONE) + // { + // try + // { + // CDOResource resource = transaction.getObject(resourceWriter); + // fail("Exception expected"); + // } + // catch (Exception ex) + // { + // // SUCCESS + // } + // } + // else + // { + // CDOResource resource = transaction.getObject(resourceWriter); + // assertEquals(expected, resource.cdoPermission()); + // + // if (expected != CDOPermission.NONE) + // { + // Company company = (Company)resource.getContents().get(0); + // assertEquals(expected, CDOUtil.getCDOObject(company).cdoPermission()); + // } + // } } private ISecurityManager startSecureRepository(ISecurityManager.RealmOperation operation) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSession.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSession.java index ea09342066..33f6081e6c 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSession.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSession.java @@ -39,6 +39,7 @@ import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EPackage.Registry; +import org.eclipse.emf.spi.cdo.CDOPermissionUpdater; import org.eclipse.emf.spi.cdo.CDOSessionProtocol; /** @@ -266,6 +267,20 @@ public interface CDOSession extends CDOCommonSession, CDOUpdatable, CDOTransacti public void setLobCache(CDOLobStore lobCache); /** + * Returns the {@link CDOPermissionUpdater permission updater} currently being used by this session. + * + * @since 4.3 + */ + public CDOPermissionUpdater getPermissionUpdater(); + + /** + * Sets the {@link CDOPermissionUpdater permission updater} to be used by this session. + * + * @since 4.3 + */ + public void setPermissionUpdater(CDOPermissionUpdater permissionUpdater); + + /** * An {@link IOptionsEvent options event} fired when the * {@link Options#setGeneratedPackageEmulationEnabled(boolean) generated package emulation enabled} option of a * {@link CDOSession session} has changed. @@ -303,6 +318,19 @@ public interface CDOSession extends CDOCommonSession, CDOUpdatable, CDOTransacti public interface LobCacheEvent extends IOptionsEvent { } + + /** + * An {@link IOptionsEvent options event} fired when the {@link Options#setPermissionUpdater(CDOPermissionUpdater) permission updater} + * option of a {@link CDOSession session} has changed. + * + * @author Eike Stepper + * @since 4.3 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ + public interface PermissionUpdaterEvent extends IOptionsEvent + { + } } /** diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java index 7ccdf01477..8d9c36debe 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java @@ -461,13 +461,13 @@ public abstract class CDOLegacyWrapper extends CDOObjectWrapper Counter counter = recursionCounter.get(); InternalCDOResource resource = null; + boolean bypassPermissionChecks = revision.bypassPermissionChecks(true); try { registerWrapper(this); counter.increment(); viewAndState.view.registerObject(this); - revision.bypassPermissionChecks(true); revisionToInstanceResource(); revisionToInstanceContainer(); @@ -496,7 +496,7 @@ public abstract class CDOLegacyWrapper extends CDOObjectWrapper } finally { - revision.bypassPermissionChecks(false); + revision.bypassPermissionChecks(bypassPermissionChecks); if (resource != null) { diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java index 7cd74525b4..59e121ab0f 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java @@ -15,6 +15,7 @@ */ package org.eclipse.emf.internal.cdo.session; +import org.eclipse.emf.cdo.CDOState; import org.eclipse.emf.cdo.common.CDOCommonRepository; import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; @@ -117,8 +118,10 @@ import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.spi.cdo.CDOPermissionUpdater; import org.eclipse.emf.spi.cdo.CDOSessionProtocol; import org.eclipse.emf.spi.cdo.CDOSessionProtocol.RefreshSessionResult; +import org.eclipse.emf.spi.cdo.InternalCDOObject; import org.eclipse.emf.spi.cdo.InternalCDORemoteSessionManager; import org.eclipse.emf.spi.cdo.InternalCDOSession; import org.eclipse.emf.spi.cdo.InternalCDOTransaction; @@ -641,13 +644,16 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme { Map<CDOID, InternalCDORevision> oldRevisions = viewedRevisions.get(branch); + InternalCDORevisionManager revisionManager = getRevisionManager(); List<CDORevisionKey> changedObjects = new ArrayList<CDORevisionKey>(); List<InternalCDORevision> newRevisions = result.getChangedObjects(branch); + for (InternalCDORevision newRevision : newRevisions) { - getRevisionManager().addRevision(newRevision); + revisionManager.addRevision(newRevision); - InternalCDORevision oldRevision = oldRevisions.get(newRevision.getID()); + CDOID id = newRevision.getID(); + InternalCDORevision oldRevision = oldRevisions.get(id); InternalCDORevisionDelta delta = newRevision.compare(oldRevision); changedObjects.add(delta); } @@ -655,13 +661,15 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme List<CDOIDAndVersion> detachedObjects = result.getDetachedObjects(branch); for (CDOIDAndVersion detachedObject : detachedObjects) { - getRevisionManager().reviseLatest(detachedObject.getID(), branch); + CDOID id = detachedObject.getID(); + revisionManager.reviseLatest(id, branch); } + long lastUpdateTime = result.getLastUpdateTime(); for (InternalCDOView view : branchViews) { - view.invalidate(view.getBranch(), result.getLastUpdateTime(), changedObjects, detachedObjects, oldRevisions, - false, true); + CDOBranch viewBranch = view.getBranch(); + view.invalidate(viewBranch, lastUpdateTime, changedObjects, detachedObjects, oldRevisions, false, true); } } @@ -1339,6 +1347,8 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme private CDOLobStore lobCache = CDOLobStoreImpl.INSTANCE; + private CDOPermissionUpdater permissionUpdater = CDOPermissionUpdater.SERVER; + public OptionsImpl() { setCollectionLoadingPolicy(null); // Init default @@ -1537,6 +1547,37 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme } } + public CDOPermissionUpdater getPermissionUpdater() + { + synchronized (this) + { + return permissionUpdater; + } + } + + public void setPermissionUpdater(CDOPermissionUpdater permissionUpdater) + { + IListener[] listeners = getListeners(); + IEvent event = null; + + synchronized (this) + { + if (this.permissionUpdater != permissionUpdater) + { + this.permissionUpdater = permissionUpdater; + if (listeners != null) + { + event = new PermissionUpdaterEventImpl(); + } + } + } + + if (event != null) + { + fireEvent(event, listeners); + } + } + /** * @author Eike Stepper */ @@ -1649,6 +1690,19 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme super(OptionsImpl.this); } } + + /** + * @author Eike Stepper + */ + private final class PermissionUpdaterEventImpl extends OptionsEvent implements PermissionUpdaterEvent + { + private static final long serialVersionUID = 1L; + + public PermissionUpdaterEventImpl() + { + super(OptionsImpl.this); + } + } } /** @@ -1821,10 +1875,17 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme try { + InternalCDOView[] views = getViews(); Map<CDOID, InternalCDORevision> oldRevisions = null; + boolean success = commitInfo.getBranch() != null; if (success) { + if (clearPermissionCache) + { + updatePermissions(views); + } + oldRevisions = reviseRevisions(); } @@ -1839,7 +1900,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme commitInfoManager.notifyCommitInfoHandlers(commitInfo); } - for (InternalCDOView view : getViews()) + for (InternalCDOView view : views) { invalidateView(commitInfo, view, sender, oldRevisions, clearResourcePathCache); } @@ -1903,14 +1964,15 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme newRevision.setVersion(target.getVersion()); } + boolean bypassPermissionChecks = newRevision.bypassPermissionChecks(true); + try { - newRevision.bypassPermissionChecks(true); revisionDelta.apply(newRevision); } finally { - newRevision.bypassPermissionChecks(false); + newRevision.bypassPermissionChecks(bypassPermissionChecks); newRevision.freeze(); } @@ -1943,6 +2005,56 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme return oldRevisions; } + private Map<InternalCDORevision, CDOPermission> updatePermissions(InternalCDOView[] views) + { + CDOPermissionUpdater permissionUpdater = options().getPermissionUpdater(); + if (permissionUpdater != null) + { + CDOBranchPoint head = getBranchManager().getMainBranch().getHead(); + Set<InternalCDORevision> revisions = new HashSet<InternalCDORevision>(); + + for (int i = 0; i < views.length; i++) + { + InternalCDOView view = views[i]; + if (!head.equals(view)) + { + throw new IllegalStateException("Security not supported with auditing or branching"); + } + + for (InternalCDOObject object : view.getObjects().values()) + { + InternalCDORevision revision; + + CDOState state = object.cdoState(); + switch (state) + { + case CLEAN: + revision = object.cdoRevision(); + break; + + case DIRTY: + case CONFLICT: + CDOID id = object.cdoID(); + revision = getRevisionManager().getRevision(id, head, 0, CDORevision.DEPTH_NONE, false); + break; + + default: + continue; + } + + if (revision != null) + { + revisions.add(revision); + } + } + } + + return permissionUpdater.updatePermissions(CDOSessionImpl.this, revisions); + } + + return null; + } + private void addNewRevision(InternalCDORevision newRevision) { if (newPermissions != null) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java index 0c084a2b9f..31224e7359 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java @@ -30,6 +30,7 @@ import org.eclipse.emf.cdo.common.model.CDOPackageUnit; import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; import org.eclipse.emf.cdo.common.revision.CDORevisionKey; +import org.eclipse.emf.cdo.common.security.CDOPermission; import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.session.CDOSession.ExceptionHandler; import org.eclipse.emf.cdo.session.remote.CDORemoteSession; @@ -915,6 +916,22 @@ public class DelegatingSessionProtocol extends Lifecycle implements CDOSessionPr } } + public Map<InternalCDORevision, CDOPermission> loadPermissions(InternalCDORevision[] revisions) + { + int attempt = 0; + for (;;) + { + try + { + return delegate.loadPermissions(revisions); + } + catch (Exception ex) + { + handleException(++attempt, ex); + } + } + } + @Override protected void doActivate() throws Exception { diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java index 30e942c006..73f451b239 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java @@ -644,15 +644,15 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb EAttribute nameFeature = EresourcePackage.eINSTANCE.getCDOResourceNode_Name(); CDOList list; + boolean bypassPermissionChecks = folderRevision.bypassPermissionChecks(true); try { - folderRevision.bypassPermissionChecks(true); list = folderRevision.getList(nodesFeature); } finally { - folderRevision.bypassPermissionChecks(false); + folderRevision.bypassPermissionChecks(bypassPermissionChecks); } CDOStore store = getStore(); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOPermissionUpdater.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOPermissionUpdater.java new file mode 100644 index 0000000000..eea93477c9 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOPermissionUpdater.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2004-2013 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.spi.cdo; + +import org.eclipse.emf.cdo.common.security.CDOPermission; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; + +import java.util.Map; +import java.util.Set; + +/** + * @author Eike Stepper + * @since 4.3 + */ +public interface CDOPermissionUpdater +{ + public static final CDOPermissionUpdater SERVER = new CDOPermissionUpdater() + { + public Map<InternalCDORevision, CDOPermission> updatePermissions(InternalCDOSession session, + Set<InternalCDORevision> revisions) + { + InternalCDORevision[] revisionArray = revisions.toArray(new InternalCDORevision[revisions.size()]); + CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); + return sessionProtocol.loadPermissions(revisionArray); + } + }; + + public Map<InternalCDORevision, CDOPermission> updatePermissions(InternalCDOSession session, + Set<InternalCDORevision> revisions); +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java index 9d2ec27a69..fb3625cc19 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java @@ -291,6 +291,11 @@ public interface CDOSessionProtocol extends CDOProtocol, PackageLoader, BranchLo public void enableLockNotifications(int viewID, boolean enable); /** + * @since 4.3 + */ + public Map<InternalCDORevision, CDOPermission> loadPermissions(InternalCDORevision[] revisions); + + /** * If the meaning of this type isn't clear, there really should be more of a description here... * * @author Eike Stepper |