Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2012-05-01 10:06:14 +0000
committerEike Stepper2012-05-01 10:06:14 +0000
commitb4d78150e6b5b2277fa70ee3df3ccc1c2e6d2b48 (patch)
treedb9fc0686e45436cb3ba6592fa236ee50ef611f8 /plugins
parent7698f3a56562e5e538ce5584e427ada9390b9e87 (diff)
parentcbf2aed7453b7ac4e9282aba2910bce1bd1a75ff (diff)
downloadcdo-b4d78150e6b5b2277fa70ee3df3ccc1c2e6d2b48.tar.gz
cdo-b4d78150e6b5b2277fa70ee3df3ccc1c2e6d2b48.tar.xz
cdo-b4d78150e6b5b2277fa70ee3df3ccc1c2e6d2b48.zip
Merge branch 'master' into bugs/369646
Diffstat (limited to 'plugins')
-rw-r--r--plugins/org.eclipse.emf.cdo.common/META-INF/MANIFEST.MF1
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataInput.java334
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataOutput.java342
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevision.java240
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/CDOPermission.java64
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/CDOPermissionProvider.java54
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/NoPermissionException.java40
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/package-info.java16
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java1302
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataOutputImpl.java1126
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java56
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/AbstractCDORevision.java424
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java1703
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevision.java681
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevision.java250
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/StubCDORevision.java555
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate.teneo/src/org/eclipse/emf/cdo/server/hibernate/teneo/CDOEntityMapper.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndication.java323
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java1171
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java13
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java3006
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IPermissionManager.java24
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java173
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java174
-rw-r--r--plugins/org.eclipse.emf.cdo.tests.db/build.properties65
-rw-r--r--plugins/org.eclipse.emf.cdo.tests.db4o/build.properties43
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/META-INF/MANIFEST.MF3
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/build.properties88
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_343084_Test.java240
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java15
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java2298
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java2087
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java1427
33 files changed, 9558 insertions, 8785 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.common/META-INF/MANIFEST.MF
index 0b80784f1d..419b2d960b 100644
--- a/plugins/org.eclipse.emf.cdo.common/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.common/META-INF/MANIFEST.MF
@@ -26,6 +26,7 @@ Export-Package: org.eclipse.emf.cdo.common;version="4.1.0",
org.eclipse.emf.cdo.common.protocol;version="4.1.0",
org.eclipse.emf.cdo.common.revision;version="4.1.0",
org.eclipse.emf.cdo.common.revision.delta;version="4.1.0",
+ org.eclipse.emf.cdo.common.security;version="4.1.0",
org.eclipse.emf.cdo.common.util;version="4.1.0",
org.eclipse.emf.cdo.internal.common;version="4.1.0";
x-friends:="org.eclipse.emf.cdo.common,
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataInput.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataInput.java
index 0cb9d5915d..85be7ab966 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataInput.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataInput.java
@@ -1,167 +1,167 @@
-/*
- * Copyright (c) 2004 - 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
- * Simon McDuff - maintenance
- */
-package org.eclipse.emf.cdo.common.protocol;
-
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
-import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
-import org.eclipse.emf.cdo.common.commit.CDOCommitData;
-import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDReference;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
-import org.eclipse.emf.cdo.common.lock.CDOLockState;
-import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
-import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
-import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
-import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
-import org.eclipse.emf.cdo.common.model.CDOType;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
-import org.eclipse.emf.cdo.common.revision.CDOList;
-import org.eclipse.emf.cdo.common.revision.CDORevisable;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
-import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
-
-import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
-import org.eclipse.net4j.util.io.ExtendedDataInput;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EClassifier;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.resource.ResourceSet;
-
-import java.io.IOException;
-
-/**
- * Provides I/O methods for reading various CDO data types and concepts from streams.
- *
- * @author Eike Stepper
- * @since 3.0
- * @noextend This interface is not intended to be extended by clients.
- * @noimplement This interface is not intended to be implemented by clients.
- */
-public interface CDODataInput extends ExtendedDataInput
-{
- // /////////////////////////////////////////////////////////////////////////////////////////////////
-
- public CDOPackageUnit readCDOPackageUnit(ResourceSet resourceSet) throws IOException;
-
- public CDOPackageUnit[] readCDOPackageUnits(ResourceSet resourceSet) throws IOException;
-
- public CDOPackageUnit.Type readCDOPackageUnitType() throws IOException;
-
- public CDOPackageInfo readCDOPackageInfo() throws IOException;
-
- public CDOClassifierRef readCDOClassifierRef() throws IOException;
-
- public EClassifier readCDOClassifierRefAndResolve() throws IOException;
-
- public String readCDOPackageURI() throws IOException;
-
- public CDOType readCDOType() throws IOException;
-
- // /////////////////////////////////////////////////////////////////////////////////////////////////
-
- public CDOBranch readCDOBranch() throws IOException;
-
- public CDOBranchPoint readCDOBranchPoint() throws IOException;
-
- public CDOBranchVersion readCDOBranchVersion() throws IOException;
-
- public CDOChangeSetData readCDOChangeSetData() throws IOException;
-
- public CDOCommitData readCDOCommitData() throws IOException;
-
- public CDOCommitInfo readCDOCommitInfo() throws IOException;
-
- // /////////////////////////////////////////////////////////////////////////////////////////////////
-
- public CDOID readCDOID() throws IOException;
-
- /**
- * @since 4.0
- */
- public CDOIDReference readCDOIDReference() throws IOException;
-
- /**
- * @since 4.0
- */
- public CDOIDAndVersion readCDOIDAndVersion() throws IOException;
-
- /**
- * @since 4.0
- */
- public CDOIDAndBranch readCDOIDAndBranch() throws IOException;
-
- // /////////////////////////////////////////////////////////////////////////////////////////////////
-
- public CDORevisionKey readCDORevisionKey() throws IOException;
-
- public CDORevision readCDORevision() throws IOException;
-
- /**
- * @since 4.1
- */
- public CDORevision readCDORevision(boolean freeze) throws IOException;
-
- /**
- * @since 4.0
- */
- public CDORevisable readCDORevisable() throws IOException;
-
- public CDOList readCDOList(EClass owner, EStructuralFeature feature) throws IOException;
-
- public Object readCDOFeatureValue(EStructuralFeature feature) throws IOException;
-
- public CDORevisionDelta readCDORevisionDelta() throws IOException;
-
- public CDOFeatureDelta readCDOFeatureDelta(EClass owner) throws IOException;
-
- /**
- * Read either a CDORevision or a primitive value.
- */
- public Object readCDORevisionOrPrimitive() throws IOException;
-
- /**
- * Read either a CDORevision, a primitive value or a EClass.
- */
- public Object readCDORevisionOrPrimitiveOrClassifier() throws IOException;
-
- // /////////////////////////////////////////////////////////////////////////////////////////////////
-
- public LockType readCDOLockType() throws IOException;
-
- /**
- * @since 4.1
- */
- public CDOLockChangeInfo readCDOLockChangeInfo() throws IOException;
-
- /**
- * @since 4.1
- */
- public CDOLockOwner readCDOLockOwner() throws IOException;
-
- /**
- * @since 4.1
- */
- public CDOLockState readCDOLockState() throws IOException;
-
- /**
- * @since 4.1
- */
- public LockArea readCDOLockArea() throws IOException;
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Simon McDuff - maintenance
+ */
+package org.eclipse.emf.cdo.common.protocol;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDReference;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.model.CDOType;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevisable;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.io.ExtendedDataInput;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+
+import java.io.IOException;
+
+/**
+ * Provides I/O methods for reading various CDO data types and concepts from streams.
+ *
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface CDODataInput extends ExtendedDataInput
+{
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public CDOPackageUnit readCDOPackageUnit(ResourceSet resourceSet) throws IOException;
+
+ public CDOPackageUnit[] readCDOPackageUnits(ResourceSet resourceSet) throws IOException;
+
+ public CDOPackageUnit.Type readCDOPackageUnitType() throws IOException;
+
+ public CDOPackageInfo readCDOPackageInfo() throws IOException;
+
+ public CDOClassifierRef readCDOClassifierRef() throws IOException;
+
+ public EClassifier readCDOClassifierRefAndResolve() throws IOException;
+
+ public String readCDOPackageURI() throws IOException;
+
+ public CDOType readCDOType() throws IOException;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public CDOBranch readCDOBranch() throws IOException;
+
+ public CDOBranchPoint readCDOBranchPoint() throws IOException;
+
+ public CDOBranchVersion readCDOBranchVersion() throws IOException;
+
+ public CDOChangeSetData readCDOChangeSetData() throws IOException;
+
+ public CDOCommitData readCDOCommitData() throws IOException;
+
+ public CDOCommitInfo readCDOCommitInfo() throws IOException;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public CDOID readCDOID() throws IOException;
+
+ /**
+ * @since 4.0
+ */
+ public CDOIDReference readCDOIDReference() throws IOException;
+
+ /**
+ * @since 4.0
+ */
+ public CDOIDAndVersion readCDOIDAndVersion() throws IOException;
+
+ /**
+ * @since 4.0
+ */
+ public CDOIDAndBranch readCDOIDAndBranch() throws IOException;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public CDORevisionKey readCDORevisionKey() throws IOException;
+
+ public CDORevision readCDORevision() throws IOException;
+
+ /**
+ * @since 4.1
+ */
+ public CDORevision readCDORevision(boolean freeze) throws IOException;
+
+ /**
+ * @since 4.0
+ */
+ public CDORevisable readCDORevisable() throws IOException;
+
+ public CDOList readCDOList(EClass owner, EStructuralFeature feature) throws IOException;
+
+ public Object readCDOFeatureValue(EStructuralFeature feature) throws IOException;
+
+ public CDORevisionDelta readCDORevisionDelta() throws IOException;
+
+ public CDOFeatureDelta readCDOFeatureDelta(EClass owner) throws IOException;
+
+ /**
+ * Read either a CDORevision or a primitive value.
+ */
+ public Object readCDORevisionOrPrimitive() throws IOException;
+
+ /**
+ * Read either a CDORevision, a primitive value or a EClass.
+ */
+ public Object readCDORevisionOrPrimitiveOrClassifier() throws IOException;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public LockType readCDOLockType() throws IOException;
+
+ /**
+ * @since 4.1
+ */
+ public CDOLockChangeInfo readCDOLockChangeInfo() throws IOException;
+
+ /**
+ * @since 4.1
+ */
+ public CDOLockOwner readCDOLockOwner() throws IOException;
+
+ /**
+ * @since 4.1
+ */
+ public CDOLockState readCDOLockState() throws IOException;
+
+ /**
+ * @since 4.1
+ */
+ public LockArea readCDOLockArea() throws IOException;
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataOutput.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataOutput.java
index 07f9aa4390..8f779ac388 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataOutput.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataOutput.java
@@ -1,168 +1,174 @@
-/*
- * Copyright (c) 2004 - 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
- * Simon McDuff - maintenance
- */
-package org.eclipse.emf.cdo.common.protocol;
-
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
-import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
-import org.eclipse.emf.cdo.common.commit.CDOCommitData;
-import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDProvider;
-import org.eclipse.emf.cdo.common.id.CDOIDReference;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
-import org.eclipse.emf.cdo.common.lock.CDOLockState;
-import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
-import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
-import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
-import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
-import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
-import org.eclipse.emf.cdo.common.model.CDOType;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
-import org.eclipse.emf.cdo.common.revision.CDOList;
-import org.eclipse.emf.cdo.common.revision.CDORevisable;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
-import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
-
-import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
-import org.eclipse.net4j.util.io.ExtendedDataOutput;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EClassifier;
-import org.eclipse.emf.ecore.EStructuralFeature;
-
-import java.io.IOException;
-
-/**
- * Provides I/O methods for writing various CDO data types and concepts to streams.
- *
- * @author Eike Stepper
- * @since 3.0
- * @noextend This interface is not intended to be extended by clients.
- * @noimplement This interface is not intended to be implemented by clients.
- */
-public interface CDODataOutput extends ExtendedDataOutput
-{
- public CDOPackageRegistry getPackageRegistry();
-
- public CDOIDProvider getIDProvider();
-
- // /////////////////////////////////////////////////////////////////////////////////////////////////
-
- public void writeCDOPackageUnit(CDOPackageUnit packageUnit, boolean withPackages) throws IOException;
-
- public void writeCDOPackageUnits(CDOPackageUnit... packageUnit) throws IOException;
-
- public void writeCDOPackageUnitType(CDOPackageUnit.Type type) throws IOException;
-
- public void writeCDOPackageInfo(CDOPackageInfo packageInfo) throws IOException;
-
- public void writeCDOClassifierRef(CDOClassifierRef eClassifierRef) throws IOException;
-
- public void writeCDOClassifierRef(EClassifier eClassifier) throws IOException;
-
- public void writeCDOPackageURI(String uri) throws IOException;
-
- public void writeCDOType(CDOType cdoType) throws IOException;
-
- // /////////////////////////////////////////////////////////////////////////////////////////////////
-
- public void writeCDOBranch(CDOBranch branch) throws IOException;
-
- public void writeCDOBranchPoint(CDOBranchPoint branchPoint) throws IOException;
-
- public void writeCDOBranchVersion(CDOBranchVersion branchVersion) throws IOException;
-
- public void writeCDOChangeSetData(CDOChangeSetData changeSetData) throws IOException;
-
- public void writeCDOCommitData(CDOCommitData commitData) throws IOException;
-
- public void writeCDOCommitInfo(CDOCommitInfo commitInfo) throws IOException;
-
- // /////////////////////////////////////////////////////////////////////////////////////////////////
-
- public void writeCDOID(CDOID id) throws IOException;
-
- /**
- * @since 4.0
- */
- public void writeCDOIDReference(CDOIDReference idReference) throws IOException;
-
- /**
- * @since 4.0
- */
- public void writeCDOIDAndVersion(CDOIDAndVersion idAndVersion) throws IOException;
-
- /**
- * @since 4.0
- */
- public void writeCDOIDAndBranch(CDOIDAndBranch idAndBranch) throws IOException;
-
- // /////////////////////////////////////////////////////////////////////////////////////////////////
-
- public void writeCDORevisionKey(CDORevisionKey revisionKey) throws IOException;
-
- public void writeCDORevision(CDORevision revision, int referenceChunk) throws IOException;
-
- /**
- * @since 4.0
- */
- public void writeCDORevisable(CDORevisable revisable) throws IOException;
-
- public void writeCDOList(EClass owner, EStructuralFeature feature, CDOList list, int referenceChunk)
- throws IOException;
-
- public void writeCDOFeatureValue(EStructuralFeature feature, Object value) throws IOException;
-
- public void writeCDORevisionDelta(CDORevisionDelta revisionDelta) throws IOException;
-
- public void writeCDOFeatureDelta(EClass owner, CDOFeatureDelta featureDelta) throws IOException;
-
- /**
- * Write either a CDORevision or a primitive value.
- */
- public void writeCDORevisionOrPrimitive(Object value) throws IOException;
-
- /**
- * Write either a CDORevision, a primitive value or a EClass.
- */
- public void writeCDORevisionOrPrimitiveOrClassifier(Object value) throws IOException;
-
- // /////////////////////////////////////////////////////////////////////////////////////////////////
-
- public void writeCDOLockType(LockType lockType) throws IOException;
-
- /**
- * @since 4.1
- */
- public void writeCDOLockChangeInfo(CDOLockChangeInfo lockChangeInfo) throws IOException;
-
- /**
- * @since 4.1
- */
- public void writeCDOLockState(CDOLockState lockState) throws IOException;
-
- /**
- * @since 4.1
- */
- public void writeCDOLockOwner(CDOLockOwner lockOwner) throws IOException;
-
- /**
- * @since 4.1
- */
- public void writeCDOLockArea(LockArea lockArea) throws IOException;
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Simon McDuff - maintenance
+ */
+package org.eclipse.emf.cdo.common.protocol;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDProvider;
+import org.eclipse.emf.cdo.common.id.CDOIDReference;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
+import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.model.CDOType;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevisable;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.security.CDOPermissionProvider;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.io.ExtendedDataOutput;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.io.IOException;
+
+/**
+ * Provides I/O methods for writing various CDO data types and concepts to streams.
+ *
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface CDODataOutput extends ExtendedDataOutput
+{
+ public CDOPackageRegistry getPackageRegistry();
+
+ public CDOIDProvider getIDProvider();
+
+ /**
+ * @since 4.1
+ */
+ public CDOPermissionProvider getPermissionProvider();
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public void writeCDOPackageUnit(CDOPackageUnit packageUnit, boolean withPackages) throws IOException;
+
+ public void writeCDOPackageUnits(CDOPackageUnit... packageUnit) throws IOException;
+
+ public void writeCDOPackageUnitType(CDOPackageUnit.Type type) throws IOException;
+
+ public void writeCDOPackageInfo(CDOPackageInfo packageInfo) throws IOException;
+
+ public void writeCDOClassifierRef(CDOClassifierRef eClassifierRef) throws IOException;
+
+ public void writeCDOClassifierRef(EClassifier eClassifier) throws IOException;
+
+ public void writeCDOPackageURI(String uri) throws IOException;
+
+ public void writeCDOType(CDOType cdoType) throws IOException;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public void writeCDOBranch(CDOBranch branch) throws IOException;
+
+ public void writeCDOBranchPoint(CDOBranchPoint branchPoint) throws IOException;
+
+ public void writeCDOBranchVersion(CDOBranchVersion branchVersion) throws IOException;
+
+ public void writeCDOChangeSetData(CDOChangeSetData changeSetData) throws IOException;
+
+ public void writeCDOCommitData(CDOCommitData commitData) throws IOException;
+
+ public void writeCDOCommitInfo(CDOCommitInfo commitInfo) throws IOException;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public void writeCDOID(CDOID id) throws IOException;
+
+ /**
+ * @since 4.0
+ */
+ public void writeCDOIDReference(CDOIDReference idReference) throws IOException;
+
+ /**
+ * @since 4.0
+ */
+ public void writeCDOIDAndVersion(CDOIDAndVersion idAndVersion) throws IOException;
+
+ /**
+ * @since 4.0
+ */
+ public void writeCDOIDAndBranch(CDOIDAndBranch idAndBranch) throws IOException;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public void writeCDORevisionKey(CDORevisionKey revisionKey) throws IOException;
+
+ public void writeCDORevision(CDORevision revision, int referenceChunk) throws IOException;
+
+ /**
+ * @since 4.0
+ */
+ public void writeCDORevisable(CDORevisable revisable) throws IOException;
+
+ public void writeCDOList(EClass owner, EStructuralFeature feature, CDOList list, int referenceChunk)
+ throws IOException;
+
+ public void writeCDOFeatureValue(EStructuralFeature feature, Object value) throws IOException;
+
+ public void writeCDORevisionDelta(CDORevisionDelta revisionDelta) throws IOException;
+
+ public void writeCDOFeatureDelta(EClass owner, CDOFeatureDelta featureDelta) throws IOException;
+
+ /**
+ * Write either a CDORevision or a primitive value.
+ */
+ public void writeCDORevisionOrPrimitive(Object value) throws IOException;
+
+ /**
+ * Write either a CDORevision, a primitive value or a EClass.
+ */
+ public void writeCDORevisionOrPrimitiveOrClassifier(Object value) throws IOException;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public void writeCDOLockType(LockType lockType) throws IOException;
+
+ /**
+ * @since 4.1
+ */
+ public void writeCDOLockChangeInfo(CDOLockChangeInfo lockChangeInfo) throws IOException;
+
+ /**
+ * @since 4.1
+ */
+ public void writeCDOLockState(CDOLockState lockState) throws IOException;
+
+ /**
+ * @since 4.1
+ */
+ public void writeCDOLockOwner(CDOLockOwner lockOwner) throws IOException;
+
+ /**
+ * @since 4.1
+ */
+ public void writeCDOLockArea(LockArea lockArea) throws IOException;
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevision.java
index cfb54d3a1d..d3884bc678 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevision.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevision.java
@@ -1,103 +1,137 @@
-/*
- * Copyright (c) 2004 - 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
- * Simon McDuff - delta support
- */
-package org.eclipse.emf.cdo.common.revision;
-
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
-import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
-import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EObject;
-
-/**
- * Encapsulates the immutable system information of a <b>single</b> CDO {@link EObject object} between two
- * {@link CDOCommitInfo commits} in a {@link CDOBranch branch} and provides access to its modeled
- * {@link CDORevisionData data}.
- *
- * @author Eike Stepper
- * @noextend This interface is not intended to be extended by clients.
- * @noimplement This interface is not intended to be implemented by clients.
- * @apiviz.landmark
- * @apiviz.has {@link CDORevisionData}
- */
-public interface CDORevision extends CDORevisionKey, CDORevisable
-{
- /**
- * @since 3.0
- */
- public static final int MAIN_BRANCH_ID = CDOBranch.MAIN_BRANCH_ID;
-
- /**
- * @since 3.0
- */
- public static final int FIRST_VERSION = CDOBranchVersion.FIRST_VERSION;
-
- public static final int UNCHUNKED = -1;
-
- /**
- * @since 3.0
- */
- public static final int DEPTH_NONE = 0;
-
- /**
- * @since 3.0
- */
- public static final int DEPTH_INFINITE = -1;
-
- /**
- * @since 2.0
- */
- public EClass getEClass();
-
- /**
- * Returns <code>true</code> exactly if {@link #getTimeStamp()} does not return {@link #UNSPECIFIED_DATE},
- * <code>false</code> otherwise.
- *
- * @since 3.0
- */
- public boolean isHistorical();
-
- public boolean isValid(long timeStamp);
-
- /**
- * @since 4.0
- */
- public boolean isValid(CDOBranchPoint branchPoint);
-
- /**
- * @since 2.0
- */
- public boolean isResourceNode();
-
- /**
- * @since 2.0
- */
- public boolean isResourceFolder();
-
- public boolean isResource();
-
- /**
- * @since 2.0
- */
- public CDORevisionData data();
-
- public CDORevisionDelta compare(CDORevision origin);
-
- public void merge(CDORevisionDelta delta);
-
- /**
- * @since 2.0
- */
- public CDORevision copy();
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Simon McDuff - delta support
+ */
+package org.eclipse.emf.cdo.common.revision;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.security.CDOPermission;
+import org.eclipse.emf.cdo.common.security.CDOPermissionProvider;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * Encapsulates the immutable system information of a <b>single</b> CDO {@link EObject object} between two
+ * {@link CDOCommitInfo commits} in a {@link CDOBranch branch} and provides access to its modeled
+ * {@link CDORevisionData data}.
+ *
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @apiviz.landmark
+ * @apiviz.has {@link CDORevisionData}
+ */
+public interface CDORevision extends CDORevisionKey, CDORevisable
+{
+ /**
+ * @since 3.0
+ */
+ public static final int MAIN_BRANCH_ID = CDOBranch.MAIN_BRANCH_ID;
+
+ /**
+ * @since 3.0
+ */
+ public static final int FIRST_VERSION = CDOBranchVersion.FIRST_VERSION;
+
+ public static final int UNCHUNKED = -1;
+
+ /**
+ * @since 3.0
+ */
+ public static final int DEPTH_NONE = 0;
+
+ /**
+ * @since 3.0
+ */
+ public static final int DEPTH_INFINITE = -1;
+
+ /**
+ * @since 4.1
+ */
+ public static final CDOPermissionProvider PERMISSION_PROVIDER = new CDOPermissionProvider()
+ {
+ public CDOPermission getPermission(Object protectableObject)
+ {
+ if (protectableObject instanceof CDORevision)
+ {
+ CDORevision revision = (CDORevision)protectableObject;
+ return revision.getPermission();
+ }
+
+ return CDOPermission.NONE;
+ }
+ };
+
+ /**
+ * @since 2.0
+ */
+ public EClass getEClass();
+
+ /**
+ * Returns <code>true</code> exactly if {@link #getTimeStamp()} does not return {@link #UNSPECIFIED_DATE},
+ * <code>false</code> otherwise.
+ *
+ * @since 3.0
+ */
+ public boolean isHistorical();
+
+ public boolean isValid(long timeStamp);
+
+ /**
+ * @since 4.0
+ */
+ public boolean isValid(CDOBranchPoint branchPoint);
+
+ /**
+ * @since 2.0
+ */
+ public boolean isResourceNode();
+
+ /**
+ * @since 2.0
+ */
+ public boolean isResourceFolder();
+
+ public boolean isResource();
+
+ /**
+ * @since 2.0
+ */
+ public CDORevisionData data();
+
+ public CDORevisionDelta compare(CDORevision origin);
+
+ public void merge(CDORevisionDelta delta);
+
+ /**
+ * @since 2.0
+ */
+ public CDORevision copy();
+
+ /**
+ * @since 4.1
+ */
+ public CDOPermission getPermission();
+
+ /**
+ * @since 4.1
+ */
+ public boolean isReadable();
+
+ /**
+ * @since 4.1
+ */
+ public boolean isWritable();
+}
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
new file mode 100644
index 0000000000..e101a9f2cc
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/CDOPermission.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2004 - 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.common.security;
+
+/**
+ * Describes the possible protection levels a protectable object may have.
+ * @author Eike Stepper
+ * @since 4.1
+ */
+public enum CDOPermission
+{
+ NONE(0x00), READ(0x01), WRITE(0x03);
+
+ private byte bits;
+
+ private CDOPermission(int bits)
+ {
+ this.bits = (byte)bits;
+ }
+
+ public byte getBits()
+ {
+ return bits;
+ }
+
+ /**
+ * @since 4.1
+ */
+ public boolean isReadable()
+ {
+ return this != CDOPermission.NONE;
+ }
+
+ /**
+ * @since 4.1
+ */
+ public boolean isWritable()
+ {
+ return this == CDOPermission.WRITE;
+ }
+
+ public static CDOPermission get(int bits)
+ {
+ switch (bits)
+ {
+ case 0x00:
+ return NONE;
+ case 0x01:
+ return READ;
+ case 0x03:
+ return WRITE;
+ default:
+ throw new IllegalArgumentException("Invalid bits: " + bits);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/CDOPermissionProvider.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/CDOPermissionProvider.java
new file mode 100644
index 0000000000..7bdfef532b
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/CDOPermissionProvider.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2004 - 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.common.security;
+
+/**
+ * Provides the protection level of protectable objects.
+ *
+ * @author Eike Stepper
+ * @since 4.1
+ */
+public interface CDOPermissionProvider
+{
+ public static final CDOPermissionProvider NONE = new Constant(CDOPermission.NONE);
+
+ public static final CDOPermissionProvider READ = new Constant(CDOPermission.READ);
+
+ public static final CDOPermissionProvider WRITE = new Constant(CDOPermission.WRITE);
+
+ public CDOPermission getPermission(Object protectableObject);
+
+ /**
+ * Provides a constant protection level for all protectable entities.
+ *
+ * @author Eike Stepper
+ */
+ public static final class Constant implements CDOPermissionProvider
+ {
+ private CDOPermission permission;
+
+ private Constant(CDOPermission permission)
+ {
+ this.permission = permission;
+ }
+
+ public CDOPermission getPermission(Object protectableObject)
+ {
+ return permission;
+ }
+
+ @Override
+ public String toString()
+ {
+ return permission.toString();
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/NoPermissionException.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/NoPermissionException.java
new file mode 100644
index 0000000000..8639adf069
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/NoPermissionException.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2004 - 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.common.security;
+
+/**
+ * A {@link SecurityException security exception} indicating the lack of permission required to do something.
+ *
+ * @author Eike Stepper
+ * @since 4.1
+ */
+public class NoPermissionException extends SecurityException
+{
+ private static final long serialVersionUID = 1L;
+
+ private Object protectableObject;
+
+ public NoPermissionException(Object protectableObject)
+ {
+ this(protectableObject, "No permission to access " + protectableObject);
+ }
+
+ public NoPermissionException(Object protectableObject, String message)
+ {
+ super(message);
+ this.protectableObject = protectableObject;
+ }
+
+ public Object getProtectableObject()
+ {
+ return protectableObject;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/package-info.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/package-info.java
new file mode 100644
index 0000000000..69f41cc39e
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/security/package-info.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2004 - 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
+ */
+
+/**
+ * Common concepts for dealing with permissions and protectable entities.
+ */
+package org.eclipse.emf.cdo.common.security;
+
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java
index 9013a9485b..424704583f 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java
@@ -1,651 +1,651 @@
-/*
- * Copyright (c) 2004 - 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
- * Simon McDuff - bug 213402
- */
-package org.eclipse.emf.cdo.internal.common.protocol;
-
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
-import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
-import org.eclipse.emf.cdo.common.commit.CDOCommitData;
-import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
-import org.eclipse.emf.cdo.common.commit.CDOCommitInfoManager;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOID.Type;
-import org.eclipse.emf.cdo.common.id.CDOIDReference;
-import org.eclipse.emf.cdo.common.id.CDOIDUtil;
-import org.eclipse.emf.cdo.common.lob.CDOLob;
-import org.eclipse.emf.cdo.common.lob.CDOLobStore;
-import org.eclipse.emf.cdo.common.lob.CDOLobUtil;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
-import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
-import org.eclipse.emf.cdo.common.lock.CDOLockState;
-import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
-import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
-import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
-import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
-import org.eclipse.emf.cdo.common.model.CDOModelUtil;
-import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
-import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
-import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
-import org.eclipse.emf.cdo.common.model.CDOType;
-import org.eclipse.emf.cdo.common.protocol.CDODataInput;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
-import org.eclipse.emf.cdo.common.revision.CDOList;
-import org.eclipse.emf.cdo.common.revision.CDOListFactory;
-import org.eclipse.emf.cdo.common.revision.CDORevisable;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionFactory;
-import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
-import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
-import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
-import org.eclipse.emf.cdo.internal.common.bundle.OM;
-import org.eclipse.emf.cdo.internal.common.commit.CDOChangeSetDataImpl;
-import org.eclipse.emf.cdo.internal.common.commit.CDOCommitDataImpl;
-import org.eclipse.emf.cdo.internal.common.commit.FailureCommitInfo;
-import org.eclipse.emf.cdo.internal.common.id.CDOIDExternalImpl;
-import org.eclipse.emf.cdo.internal.common.id.CDOIDObjectLongImpl;
-import org.eclipse.emf.cdo.internal.common.id.CDOIDTempObjectExternalImpl;
-import org.eclipse.emf.cdo.internal.common.id.CDOIDTempObjectImpl;
-import org.eclipse.emf.cdo.internal.common.lock.CDOLockAreaImpl;
-import org.eclipse.emf.cdo.internal.common.lock.CDOLockChangeInfoImpl;
-import org.eclipse.emf.cdo.internal.common.lock.CDOLockOwnerImpl;
-import org.eclipse.emf.cdo.internal.common.lock.CDOLockStateImpl;
-import org.eclipse.emf.cdo.internal.common.messages.Messages;
-import org.eclipse.emf.cdo.internal.common.revision.CDOIDAndBranchImpl;
-import org.eclipse.emf.cdo.internal.common.revision.CDOIDAndVersionImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOAddFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOClearFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOContainerFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOListFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOMoveFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDORemoveFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOSetFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOUnsetFeatureDeltaImpl;
-import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
-import org.eclipse.emf.cdo.spi.common.id.AbstractCDOID;
-import org.eclipse.emf.cdo.spi.common.lock.InternalCDOLockState;
-import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
-import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
-import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
-
-import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
-import org.eclipse.net4j.util.io.ExtendedDataInput;
-import org.eclipse.net4j.util.io.StringIO;
-import org.eclipse.net4j.util.om.trace.ContextTracer;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EClassifier;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.resource.ResourceSet;
-import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
-import org.eclipse.emf.ecore.util.FeatureMapUtil;
-
-import java.io.IOException;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Eike Stepper
- */
-public abstract class CDODataInputImpl extends ExtendedDataInput.Delegating implements CDODataInput
-{
- private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_PROTOCOL, CDODataInputImpl.class);
-
- public CDODataInputImpl(ExtendedDataInput delegate)
- {
- super(delegate);
- }
-
- public CDOPackageUnit readCDOPackageUnit(ResourceSet resourceSet) throws IOException
- {
- InternalCDOPackageUnit packageUnit = (InternalCDOPackageUnit)CDOModelUtil.createPackageUnit();
- packageUnit.read(this, resourceSet);
- return packageUnit;
- }
-
- public CDOPackageUnit[] readCDOPackageUnits(ResourceSet resourceSet) throws IOException
- {
- int size = readInt();
- if (TRACER.isEnabled())
- {
- TRACER.format("Reading {0} package units", size); //$NON-NLS-1$
- }
-
- CDOPackageUnit[] packageUnits = new CDOPackageUnit[size];
- for (int i = 0; i < size; i++)
- {
- packageUnits[i] = readCDOPackageUnit(resourceSet);
- }
-
- return packageUnits;
- }
-
- public CDOPackageUnit.Type readCDOPackageUnitType() throws IOException
- {
- return CDOPackageUnit.Type.values()[readByte()];
- }
-
- public CDOPackageInfo readCDOPackageInfo() throws IOException
- {
- InternalCDOPackageInfo packageInfo = (InternalCDOPackageInfo)CDOModelUtil.createPackageInfo();
- packageInfo.read(this);
- return packageInfo;
- }
-
- public String readCDOPackageURI() throws IOException
- {
- return getPackageURICompressor().read(this);
- }
-
- public CDOClassifierRef readCDOClassifierRef() throws IOException
- {
- return new CDOClassifierRef(this);
- }
-
- public EClassifier readCDOClassifierRefAndResolve() throws IOException
- {
- CDOClassifierRef classifierRef = readCDOClassifierRef();
- EClassifier classifier = classifierRef.resolve(getPackageRegistry());
- if (classifier == null)
- {
- throw new IOException("Unable to resolve " + classifierRef);
- }
-
- return classifier;
- }
-
- public CDOType readCDOType() throws IOException
- {
- byte typeID = readByte();
- return CDOModelUtil.getType(typeID);
- }
-
- public CDOBranch readCDOBranch() throws IOException
- {
- int branchID = readInt();
- return getBranchManager().getBranch(branchID);
- }
-
- public CDOBranchPoint readCDOBranchPoint() throws IOException
- {
- CDOBranch branch = readCDOBranch();
- long timeStamp = readLong();
- return branch.getPoint(timeStamp);
- }
-
- public CDOBranchVersion readCDOBranchVersion() throws IOException
- {
- CDOBranch branch = readCDOBranch();
- int version = readInt();
- return branch.getVersion(version);
- }
-
- public CDOChangeSetData readCDOChangeSetData() throws IOException
- {
- int size1 = readInt();
- List<CDOIDAndVersion> newObjects = new ArrayList<CDOIDAndVersion>(size1);
- for (int i = 0; i < size1; i++)
- {
- boolean revision = readBoolean();
- CDOIDAndVersion data = revision ? readCDORevision() : readCDOIDAndVersion();
- newObjects.add(data);
- }
-
- int size2 = readInt();
- List<CDORevisionKey> changedObjects = new ArrayList<CDORevisionKey>(size2);
- for (int i = 0; i < size2; i++)
- {
- boolean delta = readBoolean();
- CDORevisionKey data = delta ? readCDORevisionDelta() : readCDORevisionKey();
- changedObjects.add(data);
- }
-
- int size3 = readInt();
- List<CDOIDAndVersion> detachedObjects = new ArrayList<CDOIDAndVersion>(size3);
- for (int i = 0; i < size3; i++)
- {
- CDOIDAndVersion data = readCDOIDAndVersion();
- detachedObjects.add(data);
- }
-
- return new CDOChangeSetDataImpl(newObjects, changedObjects, detachedObjects);
- }
-
- public CDOCommitData readCDOCommitData() throws IOException
- {
- InternalCDOPackageRegistry packageRegistry = (InternalCDOPackageRegistry)getPackageRegistry();
- ResourceSet resourceSet = new ResourceSetImpl();
- resourceSet.setPackageRegistry(packageRegistry);
-
- int size = readInt();
- List<CDOPackageUnit> newPackageUnits = new ArrayList<CDOPackageUnit>(size);
- for (int i = 0; i < size; i++)
- {
- CDOPackageUnit data = readCDOPackageUnit(resourceSet);
- newPackageUnits.add(data);
- packageRegistry.putPackageUnit((InternalCDOPackageUnit)data);
- }
-
- CDOChangeSetData data = readCDOChangeSetData();
- return new CDOCommitDataImpl(newPackageUnits, data.getNewObjects(), data.getChangedObjects(),
- data.getDetachedObjects());
- }
-
- public CDOCommitInfo readCDOCommitInfo() throws IOException
- {
- long timeStamp = readLong();
- long previousTimeStamp = readLong();
-
- if (readBoolean())
- {
- CDOBranch branch = readCDOBranch();
- String userID = readString();
- String comment = readString();
- CDOCommitData commitData = readCDOCommitData();
-
- InternalCDOCommitInfoManager commitInfoManager = (InternalCDOCommitInfoManager)getCommitInfoManager();
- return commitInfoManager.createCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment, commitData);
- }
-
- return new FailureCommitInfo(timeStamp, previousTimeStamp);
- }
-
- public CDOLockChangeInfo readCDOLockChangeInfo() throws IOException
- {
- boolean isInvalidateAll = readBoolean();
- if (isInvalidateAll)
- {
- return CDOLockUtil.createLockChangeInfo();
- }
-
- CDOBranchPoint branchPoint = readCDOBranchPoint();
- CDOLockOwner lockOwner = readCDOLockOwner();
- Operation operation = readEnum(Operation.class);
- LockType lockType = readCDOLockType();
-
- int n = readInt();
- CDOLockState[] lockStates = new CDOLockState[n];
- for (int i = 0; i < n; i++)
- {
- lockStates[i] = readCDOLockState();
- }
-
- return new CDOLockChangeInfoImpl(branchPoint, lockOwner, lockStates, operation, lockType);
- }
-
- public LockArea readCDOLockArea() throws IOException
- {
- String durableLockingID = readString();
- CDOBranch branch = readCDOBranch();
- long timestamp = readLong();
- String userID = readString();
- boolean readOnly = readBoolean();
-
- int nLockStates = readInt();
- Map<CDOID, LockGrade> locks = new HashMap<CDOID, LockGrade>();
- for (int i = 0; i < nLockStates; i++)
- {
- CDOID key = readCDOID();
- LockGrade value = readEnum(LockGrade.class);
- locks.put(key, value);
- }
-
- return new CDOLockAreaImpl(durableLockingID, userID, branch.getPoint(timestamp), readOnly, locks);
- }
-
- public CDOLockOwner readCDOLockOwner() throws IOException
- {
- int session = readInt();
- int view = readInt();
- String lockAreaID = readString();
- boolean isDurableView = readBoolean();
- return new CDOLockOwnerImpl(session, view, lockAreaID, isDurableView);
- }
-
- public CDOLockState readCDOLockState() throws IOException
- {
- Object target;
- boolean sendingBranchWithID = readBoolean();
- if (!sendingBranchWithID)
- {
- target = readCDOID();
- }
- else
- {
- target = readCDOIDAndBranch();
- }
-
- InternalCDOLockState lockState = new CDOLockStateImpl(target);
-
- int nReadLockOwners = readInt();
- for (int i = 0; i < nReadLockOwners; i++)
- {
- CDOLockOwner lockOwner = readCDOLockOwner();
- lockState.addReadLockOwner(lockOwner);
- }
-
- boolean hasWriteLock = readBoolean();
- if (hasWriteLock)
- {
- CDOLockOwner lockOwner = readCDOLockOwner();
- lockState.setWriteLockOwner(lockOwner);
- }
-
- boolean hasWriteOption = readBoolean();
- if (hasWriteOption)
- {
- CDOLockOwner lockOwner = readCDOLockOwner();
- lockState.setWriteOptionOwner(lockOwner);
- }
-
- return lockState;
- }
-
- public LockType readCDOLockType() throws IOException
- {
- return readEnum(LockType.class);
- }
-
- public CDOID readCDOID() throws IOException
- {
- byte ordinal = readByte();
-
- // A subtype of OBJECT
- if (ordinal < 0)
- {
- // The ordinal value is negated in the stream to distinguish from the main type.
- // Note: Added 1 because ordinal start at 0, so correct by minus 1.
- return readCDOIDObject(-ordinal - 1);
- }
-
- if (TRACER.isEnabled())
- {
- String type;
- try
- {
- type = Type.values()[ordinal].toString();
- }
- catch (RuntimeException ex)
- {
- type = ex.getMessage();
- }
-
- TRACER.format("Reading CDOID of type {0} ({1})", ordinal, type); //$NON-NLS-1$
- }
-
- Type type = Type.values()[ordinal];
- switch (type)
- {
- case NULL:
- return CDOID.NULL;
-
- case TEMP_OBJECT:
- return new CDOIDTempObjectImpl(readInt());
-
- case EXTERNAL_OBJECT:
- return new CDOIDExternalImpl(readString());
-
- case EXTERNAL_TEMP_OBJECT:
- return new CDOIDTempObjectExternalImpl(readString());
-
- case OBJECT:
- {
- // should normally not occur is handled by
- // readCDOIDObject, code remains here
- // for backward compatibility
- AbstractCDOID id = new CDOIDObjectLongImpl();
- id.read(this);
- return id;
- }
-
- default:
- throw new IOException("Illegal type: " + type);
- }
- }
-
- private CDOID readCDOIDObject(int subTypeOrdinal) throws IOException
- {
- if (TRACER.isEnabled())
- {
- String subType;
-
- try
- {
- subType = CDOID.ObjectType.values()[subTypeOrdinal].toString();
- }
- catch (RuntimeException ex)
- {
- subType = ex.getMessage();
- }
-
- TRACER.format("Reading CDOIDObject of sub type {0} ({1})", subTypeOrdinal, subType); //$NON-NLS-1$
- }
-
- CDOID.ObjectType subType = CDOID.ObjectType.values()[subTypeOrdinal];
- AbstractCDOID id = CDOIDUtil.createCDOIDObject(subType);
- id.read(this);
- return id;
- }
-
- public CDOIDReference readCDOIDReference() throws IOException
- {
- return new CDOIDReference(this);
- }
-
- public CDOIDAndVersion readCDOIDAndVersion() throws IOException
- {
- CDOID id = readCDOID();
- int version = readInt();
- return new CDOIDAndVersionImpl(id, version);
- }
-
- public CDOIDAndBranch readCDOIDAndBranch() throws IOException
- {
- CDOID id = readCDOID();
- CDOBranch branch = readCDOBranch();
- return new CDOIDAndBranchImpl(id, branch);
- }
-
- public CDORevisionKey readCDORevisionKey() throws IOException
- {
- CDOID id = readCDOID();
- CDOBranch branch = readCDOBranch();
- int version = readInt();
- return CDORevisionUtil.createRevisionKey(id, branch, version);
- }
-
- public CDORevision readCDORevision() throws IOException
- {
- return readCDORevision(true);
- }
-
- public CDORevision readCDORevision(boolean freeze) throws IOException
- {
- boolean notNull = readBoolean();
- if (notNull)
- {
- InternalCDORevision revision = (InternalCDORevision)getRevisionFactory().createRevision(null);
- revision.read(this);
-
- if (freeze)
- {
- revision.freeze();
- }
-
- return revision;
- }
-
- return null;
- }
-
- public CDORevisable readCDORevisable() throws IOException
- {
- CDOBranch branch = readCDOBranch();
- int version = readInt();
- long timeStamp = readLong();
- long revised = readLong();
- return CDORevisionUtil.createRevisable(branch, version, timeStamp, revised);
- }
-
- public CDOList readCDOList(EClass owner, EStructuralFeature feature) throws IOException
- {
- int referenceChunk;
- int size = readInt();
- if (size < 0)
- {
- size = -size;
- referenceChunk = readInt();
- if (TRACER.isEnabled())
- {
- TRACER.format("Read feature {0}: size={1}, referenceChunk={2}", feature.getName(), size, referenceChunk); //$NON-NLS-1$
- }
- }
- else
- {
- referenceChunk = size;
- if (TRACER.isEnabled())
- {
- TRACER.format("Read feature {0}: size={1}", feature.getName(), size); //$NON-NLS-1$
- }
- }
-
- Object value = null;
- CDOType type = null;
- boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
- if (!isFeatureMap)
- {
- type = CDOModelUtil.getType(feature.getEType());
- }
-
- InternalCDOList list = (InternalCDOList)getListFactory().createList(size, size, referenceChunk);
- for (int j = 0; j < referenceChunk; j++)
- {
- if (isFeatureMap)
- {
- int featureID = readInt();
- EStructuralFeature innerFeature = owner.getEStructuralFeature(featureID);
- type = CDOModelUtil.getType(innerFeature.getEType());
- value = type.readValue(this);
- value = CDORevisionUtil.createFeatureMapEntry(innerFeature, value);
- }
- else
- {
- value = type.readValue(this);
- }
-
- list.set(j, value);
- if (TRACER.isEnabled())
- {
- TRACER.trace(" " + value); //$NON-NLS-1$
- }
- }
-
- return list;
- }
-
- public Object readCDOFeatureValue(EStructuralFeature feature) throws IOException
- {
- CDOType type = CDOModelUtil.getType(feature);
- Object value = type.readValue(this);
- if (value instanceof CDOLob<?>)
- {
- CDOLob<?> lob = (CDOLob<?>)value;
- CDOLobUtil.setStore(getLobStore(), lob);
- }
-
- return value;
- }
-
- public CDORevisionDelta readCDORevisionDelta() throws IOException
- {
- return new CDORevisionDeltaImpl(this);
- }
-
- public CDOFeatureDelta readCDOFeatureDelta(EClass owner) throws IOException
- {
- int typeOrdinal = readInt();
- CDOFeatureDelta.Type type = CDOFeatureDelta.Type.values()[typeOrdinal];
- switch (type)
- {
- case ADD:
- return new CDOAddFeatureDeltaImpl(this, owner);
-
- case SET:
- return new CDOSetFeatureDeltaImpl(this, owner);
-
- case LIST:
- return new CDOListFeatureDeltaImpl(this, owner);
-
- case MOVE:
- return new CDOMoveFeatureDeltaImpl(this, owner);
-
- case CLEAR:
- return new CDOClearFeatureDeltaImpl(this, owner);
-
- case REMOVE:
- return new CDORemoveFeatureDeltaImpl(this, owner);
-
- case CONTAINER:
- return new CDOContainerFeatureDeltaImpl(this, owner);
-
- case UNSET:
- return new CDOUnsetFeatureDeltaImpl(this, owner);
-
- default:
- throw new IOException(MessageFormat.format(Messages.getString("CDODataInputImpl.5"), typeOrdinal)); //$NON-NLS-1$
- }
- }
-
- public Object readCDORevisionOrPrimitive() throws IOException
- {
- CDOType type = readCDOType();
- return type.readValue(this);
- }
-
- public Object readCDORevisionOrPrimitiveOrClassifier() throws IOException
- {
- boolean isClassifier = readBoolean();
- if (isClassifier)
- {
- return readCDOClassifierRefAndResolve();
- }
-
- return readCDORevisionOrPrimitive();
- }
-
- protected StringIO getPackageURICompressor()
- {
- return StringIO.DIRECT;
- }
-
- protected abstract CDOPackageRegistry getPackageRegistry();
-
- protected abstract CDOBranchManager getBranchManager();
-
- protected abstract CDOCommitInfoManager getCommitInfoManager();
-
- protected abstract CDORevisionFactory getRevisionFactory();
-
- protected abstract CDOListFactory getListFactory();
-
- protected abstract CDOLobStore getLobStore();
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Simon McDuff - bug 213402
+ */
+package org.eclipse.emf.cdo.internal.common.protocol;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoManager;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOID.Type;
+import org.eclipse.emf.cdo.common.id.CDOIDReference;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lob.CDOLob;
+import org.eclipse.emf.cdo.common.lob.CDOLobStore;
+import org.eclipse.emf.cdo.common.lob.CDOLobUtil;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
+import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.model.CDOType;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDOListFactory;
+import org.eclipse.emf.cdo.common.revision.CDORevisable;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionFactory;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.internal.common.bundle.OM;
+import org.eclipse.emf.cdo.internal.common.commit.CDOChangeSetDataImpl;
+import org.eclipse.emf.cdo.internal.common.commit.CDOCommitDataImpl;
+import org.eclipse.emf.cdo.internal.common.commit.FailureCommitInfo;
+import org.eclipse.emf.cdo.internal.common.id.CDOIDExternalImpl;
+import org.eclipse.emf.cdo.internal.common.id.CDOIDObjectLongImpl;
+import org.eclipse.emf.cdo.internal.common.id.CDOIDTempObjectExternalImpl;
+import org.eclipse.emf.cdo.internal.common.id.CDOIDTempObjectImpl;
+import org.eclipse.emf.cdo.internal.common.lock.CDOLockAreaImpl;
+import org.eclipse.emf.cdo.internal.common.lock.CDOLockChangeInfoImpl;
+import org.eclipse.emf.cdo.internal.common.lock.CDOLockOwnerImpl;
+import org.eclipse.emf.cdo.internal.common.lock.CDOLockStateImpl;
+import org.eclipse.emf.cdo.internal.common.messages.Messages;
+import org.eclipse.emf.cdo.internal.common.revision.CDOIDAndBranchImpl;
+import org.eclipse.emf.cdo.internal.common.revision.CDOIDAndVersionImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOAddFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOClearFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOContainerFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOListFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOMoveFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDORemoveFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOSetFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOUnsetFeatureDeltaImpl;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.id.AbstractCDOID;
+import org.eclipse.emf.cdo.spi.common.lock.InternalCDOLockState;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.io.ExtendedDataInput;
+import org.eclipse.net4j.util.io.StringIO;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class CDODataInputImpl extends ExtendedDataInput.Delegating implements CDODataInput
+{
+ private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_PROTOCOL, CDODataInputImpl.class);
+
+ public CDODataInputImpl(ExtendedDataInput delegate)
+ {
+ super(delegate);
+ }
+
+ public CDOPackageUnit readCDOPackageUnit(ResourceSet resourceSet) throws IOException
+ {
+ InternalCDOPackageUnit packageUnit = (InternalCDOPackageUnit)CDOModelUtil.createPackageUnit();
+ packageUnit.read(this, resourceSet);
+ return packageUnit;
+ }
+
+ public CDOPackageUnit[] readCDOPackageUnits(ResourceSet resourceSet) throws IOException
+ {
+ int size = readInt();
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Reading {0} package units", size); //$NON-NLS-1$
+ }
+
+ CDOPackageUnit[] packageUnits = new CDOPackageUnit[size];
+ for (int i = 0; i < size; i++)
+ {
+ packageUnits[i] = readCDOPackageUnit(resourceSet);
+ }
+
+ return packageUnits;
+ }
+
+ public CDOPackageUnit.Type readCDOPackageUnitType() throws IOException
+ {
+ return CDOPackageUnit.Type.values()[readByte()];
+ }
+
+ public CDOPackageInfo readCDOPackageInfo() throws IOException
+ {
+ InternalCDOPackageInfo packageInfo = (InternalCDOPackageInfo)CDOModelUtil.createPackageInfo();
+ packageInfo.read(this);
+ return packageInfo;
+ }
+
+ public String readCDOPackageURI() throws IOException
+ {
+ return getPackageURICompressor().read(this);
+ }
+
+ public CDOClassifierRef readCDOClassifierRef() throws IOException
+ {
+ return new CDOClassifierRef(this);
+ }
+
+ public EClassifier readCDOClassifierRefAndResolve() throws IOException
+ {
+ CDOClassifierRef classifierRef = readCDOClassifierRef();
+ EClassifier classifier = classifierRef.resolve(getPackageRegistry());
+ if (classifier == null)
+ {
+ throw new IOException("Unable to resolve " + classifierRef);
+ }
+
+ return classifier;
+ }
+
+ public CDOType readCDOType() throws IOException
+ {
+ byte typeID = readByte();
+ return CDOModelUtil.getType(typeID);
+ }
+
+ public CDOBranch readCDOBranch() throws IOException
+ {
+ int branchID = readInt();
+ return getBranchManager().getBranch(branchID);
+ }
+
+ public CDOBranchPoint readCDOBranchPoint() throws IOException
+ {
+ CDOBranch branch = readCDOBranch();
+ long timeStamp = readLong();
+ return branch.getPoint(timeStamp);
+ }
+
+ public CDOBranchVersion readCDOBranchVersion() throws IOException
+ {
+ CDOBranch branch = readCDOBranch();
+ int version = readInt();
+ return branch.getVersion(version);
+ }
+
+ public CDOChangeSetData readCDOChangeSetData() throws IOException
+ {
+ int size1 = readInt();
+ List<CDOIDAndVersion> newObjects = new ArrayList<CDOIDAndVersion>(size1);
+ for (int i = 0; i < size1; i++)
+ {
+ boolean revision = readBoolean();
+ CDOIDAndVersion data = revision ? readCDORevision() : readCDOIDAndVersion();
+ newObjects.add(data);
+ }
+
+ int size2 = readInt();
+ List<CDORevisionKey> changedObjects = new ArrayList<CDORevisionKey>(size2);
+ for (int i = 0; i < size2; i++)
+ {
+ boolean delta = readBoolean();
+ CDORevisionKey data = delta ? readCDORevisionDelta() : readCDORevisionKey();
+ changedObjects.add(data);
+ }
+
+ int size3 = readInt();
+ List<CDOIDAndVersion> detachedObjects = new ArrayList<CDOIDAndVersion>(size3);
+ for (int i = 0; i < size3; i++)
+ {
+ CDOIDAndVersion data = readCDOIDAndVersion();
+ detachedObjects.add(data);
+ }
+
+ return new CDOChangeSetDataImpl(newObjects, changedObjects, detachedObjects);
+ }
+
+ public CDOCommitData readCDOCommitData() throws IOException
+ {
+ InternalCDOPackageRegistry packageRegistry = (InternalCDOPackageRegistry)getPackageRegistry();
+ ResourceSet resourceSet = new ResourceSetImpl();
+ resourceSet.setPackageRegistry(packageRegistry);
+
+ int size = readInt();
+ List<CDOPackageUnit> newPackageUnits = new ArrayList<CDOPackageUnit>(size);
+ for (int i = 0; i < size; i++)
+ {
+ CDOPackageUnit data = readCDOPackageUnit(resourceSet);
+ newPackageUnits.add(data);
+ packageRegistry.putPackageUnit((InternalCDOPackageUnit)data);
+ }
+
+ CDOChangeSetData data = readCDOChangeSetData();
+ return new CDOCommitDataImpl(newPackageUnits, data.getNewObjects(), data.getChangedObjects(),
+ data.getDetachedObjects());
+ }
+
+ public CDOCommitInfo readCDOCommitInfo() throws IOException
+ {
+ long timeStamp = readLong();
+ long previousTimeStamp = readLong();
+
+ if (readBoolean())
+ {
+ CDOBranch branch = readCDOBranch();
+ String userID = readString();
+ String comment = readString();
+ CDOCommitData commitData = readCDOCommitData();
+
+ InternalCDOCommitInfoManager commitInfoManager = (InternalCDOCommitInfoManager)getCommitInfoManager();
+ return commitInfoManager.createCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment, commitData);
+ }
+
+ return new FailureCommitInfo(timeStamp, previousTimeStamp);
+ }
+
+ public CDOLockChangeInfo readCDOLockChangeInfo() throws IOException
+ {
+ boolean isInvalidateAll = readBoolean();
+ if (isInvalidateAll)
+ {
+ return CDOLockUtil.createLockChangeInfo();
+ }
+
+ CDOBranchPoint branchPoint = readCDOBranchPoint();
+ CDOLockOwner lockOwner = readCDOLockOwner();
+ Operation operation = readEnum(Operation.class);
+ LockType lockType = readCDOLockType();
+
+ int n = readInt();
+ CDOLockState[] lockStates = new CDOLockState[n];
+ for (int i = 0; i < n; i++)
+ {
+ lockStates[i] = readCDOLockState();
+ }
+
+ return new CDOLockChangeInfoImpl(branchPoint, lockOwner, lockStates, operation, lockType);
+ }
+
+ public LockArea readCDOLockArea() throws IOException
+ {
+ String durableLockingID = readString();
+ CDOBranch branch = readCDOBranch();
+ long timestamp = readLong();
+ String userID = readString();
+ boolean readOnly = readBoolean();
+
+ int nLockStates = readInt();
+ Map<CDOID, LockGrade> locks = new HashMap<CDOID, LockGrade>();
+ for (int i = 0; i < nLockStates; i++)
+ {
+ CDOID key = readCDOID();
+ LockGrade value = readEnum(LockGrade.class);
+ locks.put(key, value);
+ }
+
+ return new CDOLockAreaImpl(durableLockingID, userID, branch.getPoint(timestamp), readOnly, locks);
+ }
+
+ public CDOLockOwner readCDOLockOwner() throws IOException
+ {
+ int session = readInt();
+ int view = readInt();
+ String lockAreaID = readString();
+ boolean isDurableView = readBoolean();
+ return new CDOLockOwnerImpl(session, view, lockAreaID, isDurableView);
+ }
+
+ public CDOLockState readCDOLockState() throws IOException
+ {
+ Object target;
+ boolean sendingBranchWithID = readBoolean();
+ if (!sendingBranchWithID)
+ {
+ target = readCDOID();
+ }
+ else
+ {
+ target = readCDOIDAndBranch();
+ }
+
+ InternalCDOLockState lockState = new CDOLockStateImpl(target);
+
+ int nReadLockOwners = readInt();
+ for (int i = 0; i < nReadLockOwners; i++)
+ {
+ CDOLockOwner lockOwner = readCDOLockOwner();
+ lockState.addReadLockOwner(lockOwner);
+ }
+
+ boolean hasWriteLock = readBoolean();
+ if (hasWriteLock)
+ {
+ CDOLockOwner lockOwner = readCDOLockOwner();
+ lockState.setWriteLockOwner(lockOwner);
+ }
+
+ boolean hasWriteOption = readBoolean();
+ if (hasWriteOption)
+ {
+ CDOLockOwner lockOwner = readCDOLockOwner();
+ lockState.setWriteOptionOwner(lockOwner);
+ }
+
+ return lockState;
+ }
+
+ public LockType readCDOLockType() throws IOException
+ {
+ return readEnum(LockType.class);
+ }
+
+ public CDOID readCDOID() throws IOException
+ {
+ byte ordinal = readByte();
+
+ // A subtype of OBJECT
+ if (ordinal < 0)
+ {
+ // The ordinal value is negated in the stream to distinguish from the main type.
+ // Note: Added 1 because ordinal start at 0, so correct by minus 1.
+ return readCDOIDObject(-ordinal - 1);
+ }
+
+ if (TRACER.isEnabled())
+ {
+ String type;
+ try
+ {
+ type = Type.values()[ordinal].toString();
+ }
+ catch (RuntimeException ex)
+ {
+ type = ex.getMessage();
+ }
+
+ TRACER.format("Reading CDOID of type {0} ({1})", ordinal, type); //$NON-NLS-1$
+ }
+
+ Type type = Type.values()[ordinal];
+ switch (type)
+ {
+ case NULL:
+ return CDOID.NULL;
+
+ case TEMP_OBJECT:
+ return new CDOIDTempObjectImpl(readInt());
+
+ case EXTERNAL_OBJECT:
+ return new CDOIDExternalImpl(readString());
+
+ case EXTERNAL_TEMP_OBJECT:
+ return new CDOIDTempObjectExternalImpl(readString());
+
+ case OBJECT:
+ {
+ // should normally not occur is handled by
+ // readCDOIDObject, code remains here
+ // for backward compatibility
+ AbstractCDOID id = new CDOIDObjectLongImpl();
+ id.read(this);
+ return id;
+ }
+
+ default:
+ throw new IOException("Illegal type: " + type);
+ }
+ }
+
+ private CDOID readCDOIDObject(int subTypeOrdinal) throws IOException
+ {
+ if (TRACER.isEnabled())
+ {
+ String subType;
+
+ try
+ {
+ subType = CDOID.ObjectType.values()[subTypeOrdinal].toString();
+ }
+ catch (RuntimeException ex)
+ {
+ subType = ex.getMessage();
+ }
+
+ TRACER.format("Reading CDOIDObject of sub type {0} ({1})", subTypeOrdinal, subType); //$NON-NLS-1$
+ }
+
+ CDOID.ObjectType subType = CDOID.ObjectType.values()[subTypeOrdinal];
+ AbstractCDOID id = CDOIDUtil.createCDOIDObject(subType);
+ id.read(this);
+ return id;
+ }
+
+ public CDOIDReference readCDOIDReference() throws IOException
+ {
+ return new CDOIDReference(this);
+ }
+
+ public CDOIDAndVersion readCDOIDAndVersion() throws IOException
+ {
+ CDOID id = readCDOID();
+ int version = readInt();
+ return new CDOIDAndVersionImpl(id, version);
+ }
+
+ public CDOIDAndBranch readCDOIDAndBranch() throws IOException
+ {
+ CDOID id = readCDOID();
+ CDOBranch branch = readCDOBranch();
+ return new CDOIDAndBranchImpl(id, branch);
+ }
+
+ public CDORevisionKey readCDORevisionKey() throws IOException
+ {
+ CDOID id = readCDOID();
+ CDOBranch branch = readCDOBranch();
+ int version = readInt();
+ return CDORevisionUtil.createRevisionKey(id, branch, version);
+ }
+
+ public CDORevision readCDORevision() throws IOException
+ {
+ return readCDORevision(true);
+ }
+
+ public CDORevision readCDORevision(boolean freeze) throws IOException
+ {
+ boolean notNull = readBoolean();
+ if (notNull)
+ {
+ InternalCDORevision revision = (InternalCDORevision)getRevisionFactory().createRevision(null);
+ revision.read(this);
+
+ if (freeze)
+ {
+ revision.freeze();
+ }
+
+ return revision;
+ }
+
+ return null;
+ }
+
+ public CDORevisable readCDORevisable() throws IOException
+ {
+ CDOBranch branch = readCDOBranch();
+ int version = readInt();
+ long timeStamp = readLong();
+ long revised = readLong();
+ return CDORevisionUtil.createRevisable(branch, version, timeStamp, revised);
+ }
+
+ public CDOList readCDOList(EClass owner, EStructuralFeature feature) throws IOException
+ {
+ int referenceChunk;
+ int size = readInt();
+ if (size < 0)
+ {
+ size = -size;
+ referenceChunk = readInt();
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Read feature {0}: size={1}, referenceChunk={2}", feature.getName(), size, referenceChunk); //$NON-NLS-1$
+ }
+ }
+ else
+ {
+ referenceChunk = size;
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Read feature {0}: size={1}", feature.getName(), size); //$NON-NLS-1$
+ }
+ }
+
+ Object value = null;
+ CDOType type = null;
+ boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
+ if (!isFeatureMap)
+ {
+ type = CDOModelUtil.getType(feature.getEType());
+ }
+
+ InternalCDOList list = (InternalCDOList)getListFactory().createList(size, size, referenceChunk);
+ for (int j = 0; j < referenceChunk; j++)
+ {
+ if (isFeatureMap)
+ {
+ int featureID = readInt();
+ EStructuralFeature innerFeature = owner.getEStructuralFeature(featureID);
+ type = CDOModelUtil.getType(innerFeature.getEType());
+ value = type.readValue(this);
+ value = CDORevisionUtil.createFeatureMapEntry(innerFeature, value);
+ }
+ else
+ {
+ value = type.readValue(this);
+ }
+
+ list.set(j, value);
+ if (TRACER.isEnabled())
+ {
+ TRACER.trace(" " + value); //$NON-NLS-1$
+ }
+ }
+
+ return list;
+ }
+
+ public Object readCDOFeatureValue(EStructuralFeature feature) throws IOException
+ {
+ CDOType type = CDOModelUtil.getType(feature);
+ Object value = type.readValue(this);
+ if (value instanceof CDOLob<?>)
+ {
+ CDOLob<?> lob = (CDOLob<?>)value;
+ CDOLobUtil.setStore(getLobStore(), lob);
+ }
+
+ return value;
+ }
+
+ public CDORevisionDelta readCDORevisionDelta() throws IOException
+ {
+ return new CDORevisionDeltaImpl(this);
+ }
+
+ public CDOFeatureDelta readCDOFeatureDelta(EClass owner) throws IOException
+ {
+ int typeOrdinal = readInt();
+ CDOFeatureDelta.Type type = CDOFeatureDelta.Type.values()[typeOrdinal];
+ switch (type)
+ {
+ case ADD:
+ return new CDOAddFeatureDeltaImpl(this, owner);
+
+ case SET:
+ return new CDOSetFeatureDeltaImpl(this, owner);
+
+ case LIST:
+ return new CDOListFeatureDeltaImpl(this, owner);
+
+ case MOVE:
+ return new CDOMoveFeatureDeltaImpl(this, owner);
+
+ case CLEAR:
+ return new CDOClearFeatureDeltaImpl(this, owner);
+
+ case REMOVE:
+ return new CDORemoveFeatureDeltaImpl(this, owner);
+
+ case CONTAINER:
+ return new CDOContainerFeatureDeltaImpl(this, owner);
+
+ case UNSET:
+ return new CDOUnsetFeatureDeltaImpl(this, owner);
+
+ default:
+ throw new IOException(MessageFormat.format(Messages.getString("CDODataInputImpl.5"), typeOrdinal)); //$NON-NLS-1$
+ }
+ }
+
+ public Object readCDORevisionOrPrimitive() throws IOException
+ {
+ CDOType type = readCDOType();
+ return type.readValue(this);
+ }
+
+ public Object readCDORevisionOrPrimitiveOrClassifier() throws IOException
+ {
+ boolean isClassifier = readBoolean();
+ if (isClassifier)
+ {
+ return readCDOClassifierRefAndResolve();
+ }
+
+ return readCDORevisionOrPrimitive();
+ }
+
+ protected StringIO getPackageURICompressor()
+ {
+ return StringIO.DIRECT;
+ }
+
+ protected abstract CDOPackageRegistry getPackageRegistry();
+
+ protected abstract CDOBranchManager getBranchManager();
+
+ protected abstract CDOCommitInfoManager getCommitInfoManager();
+
+ protected abstract CDORevisionFactory getRevisionFactory();
+
+ protected abstract CDOListFactory getListFactory();
+
+ protected abstract CDOLobStore getLobStore();
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataOutputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataOutputImpl.java
index 3853a9f162..da29833eab 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataOutputImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataOutputImpl.java
@@ -1,560 +1,566 @@
-/*
- * Copyright (c) 2004 - 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.common.protocol;
-
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
-import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
-import org.eclipse.emf.cdo.common.commit.CDOCommitData;
-import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDProvider;
-import org.eclipse.emf.cdo.common.id.CDOIDReference;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
-import org.eclipse.emf.cdo.common.lock.CDOLockState;
-import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
-import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
-import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
-import org.eclipse.emf.cdo.common.model.CDOModelUtil;
-import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
-import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
-import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
-import org.eclipse.emf.cdo.common.model.CDOType;
-import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
-import org.eclipse.emf.cdo.common.revision.CDOList;
-import org.eclipse.emf.cdo.common.revision.CDORevisable;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
-import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
-import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
-import org.eclipse.emf.cdo.internal.common.bundle.OM;
-import org.eclipse.emf.cdo.internal.common.messages.Messages;
-import org.eclipse.emf.cdo.internal.common.model.CDOTypeImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionDeltaImpl;
-import org.eclipse.emf.cdo.spi.common.id.AbstractCDOID;
-import org.eclipse.emf.cdo.spi.common.id.InternalCDOIDObject;
-import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
-import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
-
-import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
-import org.eclipse.net4j.util.io.ExtendedDataOutput;
-import org.eclipse.net4j.util.io.StringIO;
-import org.eclipse.net4j.util.om.trace.ContextTracer;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EClassifier;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.util.FeatureMap;
-import org.eclipse.emf.ecore.util.FeatureMap.Entry;
-import org.eclipse.emf.ecore.util.FeatureMapUtil;
-
-import java.io.IOException;
-import java.text.MessageFormat;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author Eike Stepper
- */
-public abstract class CDODataOutputImpl extends ExtendedDataOutput.Delegating implements CDODataOutput
-{
- private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_PROTOCOL, CDODataOutputImpl.class);
-
- public CDODataOutputImpl(ExtendedDataOutput delegate)
- {
- super(delegate);
- }
-
- public void writeCDOPackageUnit(CDOPackageUnit packageUnit, boolean withPackages) throws IOException
- {
- ((InternalCDOPackageUnit)packageUnit).write(this, withPackages);
- }
-
- public void writeCDOPackageUnits(CDOPackageUnit... packageUnits) throws IOException
- {
- int size = packageUnits.length;
- writeInt(size);
- if (TRACER.isEnabled())
- {
- TRACER.format("Writing {0} package units", size); //$NON-NLS-1$
- }
-
- for (CDOPackageUnit packageUnit : packageUnits)
- {
- writeCDOPackageUnit(packageUnit, false);
- }
- }
-
- public void writeCDOPackageUnitType(CDOPackageUnit.Type type) throws IOException
- {
- writeByte(type.ordinal());
- }
-
- public void writeCDOPackageInfo(CDOPackageInfo packageInfo) throws IOException
- {
- ((InternalCDOPackageInfo)packageInfo).write(this);
- }
-
- public void writeCDOClassifierRef(CDOClassifierRef eClassifierRef) throws IOException
- {
- eClassifierRef.write(this);
- }
-
- public void writeCDOClassifierRef(EClassifier eClassifier) throws IOException
- {
- writeCDOClassifierRef(new CDOClassifierRef(eClassifier));
- }
-
- public void writeCDOPackageURI(String uri) throws IOException
- {
- getPackageURICompressor().write(this, uri);
- }
-
- public void writeCDOType(CDOType cdoType) throws IOException
- {
- ((CDOTypeImpl)cdoType).write(this);
- }
-
- public void writeCDOBranch(CDOBranch branch) throws IOException
- {
- writeInt(branch.getID());
- }
-
- public void writeCDOBranchPoint(CDOBranchPoint branchPoint) throws IOException
- {
- writeCDOBranch(branchPoint.getBranch());
- writeLong(branchPoint.getTimeStamp());
- }
-
- public void writeCDOBranchVersion(CDOBranchVersion branchVersion) throws IOException
- {
- writeCDOBranch(branchVersion.getBranch());
- writeInt(branchVersion.getVersion());
- }
-
- public void writeCDOChangeSetData(CDOChangeSetData changeSetData) throws IOException
- {
- Collection<CDOIDAndVersion> newObjects = changeSetData.getNewObjects();
- writeInt(newObjects.size());
- for (CDOIDAndVersion data : newObjects)
- {
- if (data instanceof CDORevision)
- {
- writeBoolean(true);
- writeCDORevision((CDORevision)data, CDORevision.UNCHUNKED);
- }
- else
- {
- writeBoolean(false);
- writeCDOIDAndVersion(data);
- }
- }
-
- Collection<CDORevisionKey> changedObjects = changeSetData.getChangedObjects();
- writeInt(changedObjects.size());
- for (CDORevisionKey data : changedObjects)
- {
- if (data instanceof CDORevisionDelta)
- {
- writeBoolean(true);
- writeCDORevisionDelta((CDORevisionDelta)data);
- }
- else
- {
- writeBoolean(false);
- writeCDORevisionKey(data);
- }
- }
-
- Collection<CDOIDAndVersion> detachedObjects = changeSetData.getDetachedObjects();
- writeInt(detachedObjects.size());
- for (CDOIDAndVersion data : detachedObjects)
- {
- writeCDOIDAndVersion(data);
- }
- }
-
- public void writeCDOCommitData(CDOCommitData commitData) throws IOException
- {
- Collection<CDOPackageUnit> newPackageUnits = commitData.getNewPackageUnits();
- writeInt(newPackageUnits.size());
- for (CDOPackageUnit data : newPackageUnits)
- {
- writeCDOPackageUnit(data, false);
- }
-
- writeCDOChangeSetData(commitData);
- }
-
- public void writeCDOCommitInfo(CDOCommitInfo commitInfo) throws IOException
- {
- writeLong(commitInfo.getTimeStamp());
- writeLong(commitInfo.getPreviousTimeStamp());
-
- CDOBranch branch = commitInfo.getBranch();
- if (branch != null)
- {
- writeBoolean(true);
- writeCDOBranch(branch);
- writeString(commitInfo.getUserID());
- writeString(commitInfo.getComment());
- writeCDOCommitData(commitInfo);
- }
- else
- {
- // FailureCommitInfo
- writeBoolean(false);
- }
- }
-
- public void writeCDOLockChangeInfo(CDOLockChangeInfo lockChangeInfo) throws IOException
- {
- if (lockChangeInfo.isInvalidateAll())
- {
- writeBoolean(true);
- }
- else
- {
- writeBoolean(false);
- writeCDOBranchPoint(lockChangeInfo);
- writeCDOLockOwner(lockChangeInfo.getLockOwner());
- writeEnum(lockChangeInfo.getOperation());
- writeCDOLockType(lockChangeInfo.getLockType());
-
- CDOLockState[] lockStates = lockChangeInfo.getLockStates();
- writeInt(lockStates.length);
- for (CDOLockState lockState : lockStates)
- {
- writeCDOLockState(lockState);
- }
- }
- }
-
- public void writeCDOLockArea(LockArea lockArea) throws IOException
- {
- writeString(lockArea.getDurableLockingID());
- writeCDOBranch(lockArea.getBranch());
- writeLong(lockArea.getTimeStamp());
- writeString(lockArea.getUserID());
- writeBoolean(lockArea.isReadOnly());
-
- writeInt(lockArea.getLocks().size());
- for (Map.Entry<CDOID, LockGrade> entry : lockArea.getLocks().entrySet())
- {
- writeCDOID(entry.getKey());
- writeEnum(entry.getValue());
- }
- }
-
- public void writeCDOLockOwner(CDOLockOwner lockOwner) throws IOException
- {
- writeInt(lockOwner.getSessionID());
- writeInt(lockOwner.getViewID());
- writeString(lockOwner.getDurableLockingID());
- writeBoolean(lockOwner.isDurableView());
- }
-
- public void writeCDOLockState(CDOLockState lockState) throws IOException
- {
- Object o = lockState.getLockedObject();
- if (o instanceof CDOID)
- {
- writeBoolean(false);
- writeCDOID((CDOID)o);
- }
- else if (o instanceof CDOIDAndBranch)
- {
- writeBoolean(true);
- writeCDOIDAndBranch((CDOIDAndBranch)o);
- }
- else
- {
- throw new AssertionError("Unexpected type: " + o.getClass().getSimpleName());
- }
-
- Set<CDOLockOwner> readLockOwners = lockState.getReadLockOwners();
- writeInt(readLockOwners.size());
- for (CDOLockOwner readLockOwner : readLockOwners)
- {
- writeCDOLockOwner(readLockOwner);
- }
-
- CDOLockOwner writeLockOwner = lockState.getWriteLockOwner();
- if (writeLockOwner != null)
- {
- writeBoolean(true);
- writeCDOLockOwner(writeLockOwner);
- }
- else
- {
- writeBoolean(false);
- }
-
- CDOLockOwner writeOptionOwner = lockState.getWriteOptionOwner();
- if (writeOptionOwner != null)
- {
- writeBoolean(true);
- writeCDOLockOwner(writeOptionOwner);
- }
- else
- {
- writeBoolean(false);
- }
- }
-
- public void writeCDOLockType(LockType lockType) throws IOException
- {
- writeEnum(lockType);
- }
-
- public void writeCDOID(CDOID id) throws IOException
- {
- if (id == null)
- {
- id = CDOID.NULL;
- }
-
- if (id instanceof InternalCDOIDObject)
- {
- CDOID.ObjectType subType = ((InternalCDOIDObject)id).getSubType();
- int ordinal = subType.ordinal();
- if (TRACER.isEnabled())
- {
- TRACER.format("Writing CDOIDObject of subtype {0} ({1})", ordinal, subType); //$NON-NLS-1$
- }
-
- // Negated to distinguish between the subtypes and the maintypes.
- // Note: Added 1 because ordinal start at 0
- writeByte(-ordinal - 1);
- }
- else
- {
- CDOID.Type type = id.getType();
- int ordinal = type.ordinal();
- if (TRACER.isEnabled())
- {
- TRACER.format("Writing CDOID of type {0} ({1})", ordinal, type); //$NON-NLS-1$
- }
-
- writeByte(ordinal);
- }
-
- ((AbstractCDOID)id).write(this);
- }
-
- public void writeCDOIDReference(CDOIDReference idReference) throws IOException
- {
- idReference.write(this);
- }
-
- public void writeCDOIDAndVersion(CDOIDAndVersion idAndVersion) throws IOException
- {
- writeCDOID(idAndVersion.getID());
- writeInt(idAndVersion.getVersion());
- }
-
- public void writeCDOIDAndBranch(CDOIDAndBranch idAndBranch) throws IOException
- {
- writeCDOID(idAndBranch.getID());
- writeCDOBranch(idAndBranch.getBranch());
- }
-
- public void writeCDORevisionKey(CDORevisionKey revisionKey) throws IOException
- {
- writeCDOID(revisionKey.getID());
- writeCDOBranch(revisionKey.getBranch());
- writeInt(revisionKey.getVersion());
- }
-
- public void writeCDORevision(CDORevision revision, int referenceChunk) throws IOException
- {
- if (revision != null)
- {
- writeBoolean(true);
- ((InternalCDORevision)revision).write(this, referenceChunk);
- }
- else
- {
- writeBoolean(false);
- }
- }
-
- public void writeCDORevisable(CDORevisable revisable) throws IOException
- {
- writeCDOBranch(revisable.getBranch());
- writeInt(revisable.getVersion());
- writeLong(revisable.getTimeStamp());
- writeLong(revisable.getRevised());
- }
-
- public void writeCDOList(EClass owner, EStructuralFeature feature, CDOList list, int referenceChunk)
- throws IOException
- {
- // TODO Simon: Could most of this stuff be moved into the list?
- // (only if protected methods of this class don't need to become public)
- int size = list == null ? 0 : list.size();
- if (size > 0)
- {
- // Need to adjust the referenceChunk in case where we do not have enough value in the list.
- // Even if the referenceChunk is specified, a provider of data could have override that value.
- int sizeToLook = referenceChunk == CDORevision.UNCHUNKED ? size : Math.min(referenceChunk, size);
- for (int i = 0; i < sizeToLook; i++)
- {
- Object element = list.get(i, false);
- if (element == CDORevisionUtil.UNINITIALIZED)
- {
- referenceChunk = i;
- break;
- }
- }
- }
-
- if (referenceChunk != CDORevision.UNCHUNKED && referenceChunk < size)
- {
- // This happens only on server-side
- if (TRACER.isEnabled())
- {
- TRACER.format("Writing feature {0}: size={1}, referenceChunk={2}", feature.getName(), size, referenceChunk); //$NON-NLS-1$
- }
-
- writeInt(-size);
- writeInt(referenceChunk);
- size = referenceChunk;
- }
- else
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Writing feature {0}: size={1}", feature.getName(), size); //$NON-NLS-1$
- }
-
- writeInt(size);
- }
-
- CDOIDProvider idProvider = getIDProvider();
- boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
- for (int j = 0; j < size; j++)
- {
- Object value = list.get(j, false);
- EStructuralFeature innerFeature = feature; // Prepare for possible feature map
- if (isFeatureMap)
- {
- Entry entry = (FeatureMap.Entry)value;
- innerFeature = entry.getEStructuralFeature();
- value = entry.getValue();
-
- int featureID = owner.getFeatureID(innerFeature);
- writeInt(featureID);
- }
-
- if (value != null && innerFeature instanceof EReference)
- {
- value = idProvider.provideCDOID(value);
- }
-
- if (TRACER.isEnabled())
- {
- TRACER.trace(" " + value); //$NON-NLS-1$
- }
-
- writeCDOFeatureValue(innerFeature, value);
- }
- }
-
- public void writeCDOFeatureValue(EStructuralFeature feature, Object value) throws IOException
- {
- CDOType type = CDOModelUtil.getType(feature);
- type.writeValue(this, value);
- }
-
- public void writeCDORevisionDelta(CDORevisionDelta revisionDelta) throws IOException
- {
- ((CDORevisionDeltaImpl)revisionDelta).write(this);
- }
-
- public void writeCDOFeatureDelta(EClass owner, CDOFeatureDelta featureDelta) throws IOException
- {
- ((CDOFeatureDeltaImpl)featureDelta).write(this, owner);
- }
-
- public void writeCDORevisionOrPrimitive(Object value) throws IOException
- {
- if (value == null)
- {
- value = CDOID.NULL;
- }
- else if (value instanceof EObject)
- {
- value = getIDProvider().provideCDOID(value);
- }
- else if (value instanceof CDORevision)
- {
- value = ((CDORevision)value).getID();
- }
-
- CDOType type = null;
- if (value instanceof CDOID)
- {
- type = CDOType.OBJECT;
- }
- else
- {
- type = CDOModelUtil.getPrimitiveType(value.getClass());
- if (type == null)
- {
- throw new IllegalArgumentException(MessageFormat.format(
- Messages.getString("CDODataOutputImpl.6"), value.getClass())); //$NON-NLS-1$
- }
- }
-
- writeCDOType(type);
- type.writeValue(this, value);
- }
-
- public void writeCDORevisionOrPrimitiveOrClassifier(Object value) throws IOException
- {
- if (value instanceof EClassifier)
- {
- writeBoolean(true);
- writeCDOClassifierRef((EClass)value);
- }
- else
- {
- writeBoolean(false);
- writeCDORevisionOrPrimitive(value);
- }
- }
-
- public CDOPackageRegistry getPackageRegistry()
- {
- return null;
- }
-
- public CDOIDProvider getIDProvider()
- {
- return null;
- }
-
- protected StringIO getPackageURICompressor()
- {
- return StringIO.DIRECT;
- }
-}
+/*
+ * Copyright (c) 2004 - 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.common.protocol;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDProvider;
+import org.eclipse.emf.cdo.common.id.CDOIDReference;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
+import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.model.CDOType;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevisable;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.security.CDOPermissionProvider;
+import org.eclipse.emf.cdo.internal.common.bundle.OM;
+import org.eclipse.emf.cdo.internal.common.messages.Messages;
+import org.eclipse.emf.cdo.internal.common.model.CDOTypeImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionDeltaImpl;
+import org.eclipse.emf.cdo.spi.common.id.AbstractCDOID;
+import org.eclipse.emf.cdo.spi.common.id.InternalCDOIDObject;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.io.ExtendedDataOutput;
+import org.eclipse.net4j.util.io.StringIO;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.FeatureMap;
+import org.eclipse.emf.ecore.util.FeatureMap.Entry;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class CDODataOutputImpl extends ExtendedDataOutput.Delegating implements CDODataOutput
+{
+ private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_PROTOCOL, CDODataOutputImpl.class);
+
+ public CDODataOutputImpl(ExtendedDataOutput delegate)
+ {
+ super(delegate);
+ }
+
+ public void writeCDOPackageUnit(CDOPackageUnit packageUnit, boolean withPackages) throws IOException
+ {
+ ((InternalCDOPackageUnit)packageUnit).write(this, withPackages);
+ }
+
+ public void writeCDOPackageUnits(CDOPackageUnit... packageUnits) throws IOException
+ {
+ int size = packageUnits.length;
+ writeInt(size);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Writing {0} package units", size); //$NON-NLS-1$
+ }
+
+ for (CDOPackageUnit packageUnit : packageUnits)
+ {
+ writeCDOPackageUnit(packageUnit, false);
+ }
+ }
+
+ public void writeCDOPackageUnitType(CDOPackageUnit.Type type) throws IOException
+ {
+ writeByte(type.ordinal());
+ }
+
+ public void writeCDOPackageInfo(CDOPackageInfo packageInfo) throws IOException
+ {
+ ((InternalCDOPackageInfo)packageInfo).write(this);
+ }
+
+ public void writeCDOClassifierRef(CDOClassifierRef eClassifierRef) throws IOException
+ {
+ eClassifierRef.write(this);
+ }
+
+ public void writeCDOClassifierRef(EClassifier eClassifier) throws IOException
+ {
+ writeCDOClassifierRef(new CDOClassifierRef(eClassifier));
+ }
+
+ public void writeCDOPackageURI(String uri) throws IOException
+ {
+ getPackageURICompressor().write(this, uri);
+ }
+
+ public void writeCDOType(CDOType cdoType) throws IOException
+ {
+ ((CDOTypeImpl)cdoType).write(this);
+ }
+
+ public void writeCDOBranch(CDOBranch branch) throws IOException
+ {
+ writeInt(branch.getID());
+ }
+
+ public void writeCDOBranchPoint(CDOBranchPoint branchPoint) throws IOException
+ {
+ writeCDOBranch(branchPoint.getBranch());
+ writeLong(branchPoint.getTimeStamp());
+ }
+
+ public void writeCDOBranchVersion(CDOBranchVersion branchVersion) throws IOException
+ {
+ writeCDOBranch(branchVersion.getBranch());
+ writeInt(branchVersion.getVersion());
+ }
+
+ public void writeCDOChangeSetData(CDOChangeSetData changeSetData) throws IOException
+ {
+ Collection<CDOIDAndVersion> newObjects = changeSetData.getNewObjects();
+ writeInt(newObjects.size());
+ for (CDOIDAndVersion data : newObjects)
+ {
+ if (data instanceof CDORevision)
+ {
+ writeBoolean(true);
+ writeCDORevision((CDORevision)data, CDORevision.UNCHUNKED);
+ }
+ else
+ {
+ writeBoolean(false);
+ writeCDOIDAndVersion(data);
+ }
+ }
+
+ Collection<CDORevisionKey> changedObjects = changeSetData.getChangedObjects();
+ writeInt(changedObjects.size());
+ for (CDORevisionKey data : changedObjects)
+ {
+ if (data instanceof CDORevisionDelta)
+ {
+ writeBoolean(true);
+ writeCDORevisionDelta((CDORevisionDelta)data);
+ }
+ else
+ {
+ writeBoolean(false);
+ writeCDORevisionKey(data);
+ }
+ }
+
+ Collection<CDOIDAndVersion> detachedObjects = changeSetData.getDetachedObjects();
+ writeInt(detachedObjects.size());
+ for (CDOIDAndVersion data : detachedObjects)
+ {
+ writeCDOIDAndVersion(data);
+ }
+ }
+
+ public void writeCDOCommitData(CDOCommitData commitData) throws IOException
+ {
+ Collection<CDOPackageUnit> newPackageUnits = commitData.getNewPackageUnits();
+ writeInt(newPackageUnits.size());
+ for (CDOPackageUnit data : newPackageUnits)
+ {
+ writeCDOPackageUnit(data, false);
+ }
+
+ writeCDOChangeSetData(commitData);
+ }
+
+ public void writeCDOCommitInfo(CDOCommitInfo commitInfo) throws IOException
+ {
+ writeLong(commitInfo.getTimeStamp());
+ writeLong(commitInfo.getPreviousTimeStamp());
+
+ CDOBranch branch = commitInfo.getBranch();
+ if (branch != null)
+ {
+ writeBoolean(true);
+ writeCDOBranch(branch);
+ writeString(commitInfo.getUserID());
+ writeString(commitInfo.getComment());
+ writeCDOCommitData(commitInfo);
+ }
+ else
+ {
+ // FailureCommitInfo
+ writeBoolean(false);
+ }
+ }
+
+ public void writeCDOLockChangeInfo(CDOLockChangeInfo lockChangeInfo) throws IOException
+ {
+ if (lockChangeInfo.isInvalidateAll())
+ {
+ writeBoolean(true);
+ }
+ else
+ {
+ writeBoolean(false);
+ writeCDOBranchPoint(lockChangeInfo);
+ writeCDOLockOwner(lockChangeInfo.getLockOwner());
+ writeEnum(lockChangeInfo.getOperation());
+ writeCDOLockType(lockChangeInfo.getLockType());
+
+ CDOLockState[] lockStates = lockChangeInfo.getLockStates();
+ writeInt(lockStates.length);
+ for (CDOLockState lockState : lockStates)
+ {
+ writeCDOLockState(lockState);
+ }
+ }
+ }
+
+ public void writeCDOLockArea(LockArea lockArea) throws IOException
+ {
+ writeString(lockArea.getDurableLockingID());
+ writeCDOBranch(lockArea.getBranch());
+ writeLong(lockArea.getTimeStamp());
+ writeString(lockArea.getUserID());
+ writeBoolean(lockArea.isReadOnly());
+
+ writeInt(lockArea.getLocks().size());
+ for (Map.Entry<CDOID, LockGrade> entry : lockArea.getLocks().entrySet())
+ {
+ writeCDOID(entry.getKey());
+ writeEnum(entry.getValue());
+ }
+ }
+
+ public void writeCDOLockOwner(CDOLockOwner lockOwner) throws IOException
+ {
+ writeInt(lockOwner.getSessionID());
+ writeInt(lockOwner.getViewID());
+ writeString(lockOwner.getDurableLockingID());
+ writeBoolean(lockOwner.isDurableView());
+ }
+
+ public void writeCDOLockState(CDOLockState lockState) throws IOException
+ {
+ Object o = lockState.getLockedObject();
+ if (o instanceof CDOID)
+ {
+ writeBoolean(false);
+ writeCDOID((CDOID)o);
+ }
+ else if (o instanceof CDOIDAndBranch)
+ {
+ writeBoolean(true);
+ writeCDOIDAndBranch((CDOIDAndBranch)o);
+ }
+ else
+ {
+ throw new AssertionError("Unexpected type: " + o.getClass().getSimpleName());
+ }
+
+ Set<CDOLockOwner> readLockOwners = lockState.getReadLockOwners();
+ writeInt(readLockOwners.size());
+ for (CDOLockOwner readLockOwner : readLockOwners)
+ {
+ writeCDOLockOwner(readLockOwner);
+ }
+
+ CDOLockOwner writeLockOwner = lockState.getWriteLockOwner();
+ if (writeLockOwner != null)
+ {
+ writeBoolean(true);
+ writeCDOLockOwner(writeLockOwner);
+ }
+ else
+ {
+ writeBoolean(false);
+ }
+
+ CDOLockOwner writeOptionOwner = lockState.getWriteOptionOwner();
+ if (writeOptionOwner != null)
+ {
+ writeBoolean(true);
+ writeCDOLockOwner(writeOptionOwner);
+ }
+ else
+ {
+ writeBoolean(false);
+ }
+ }
+
+ public void writeCDOLockType(LockType lockType) throws IOException
+ {
+ writeEnum(lockType);
+ }
+
+ public void writeCDOID(CDOID id) throws IOException
+ {
+ if (id == null)
+ {
+ id = CDOID.NULL;
+ }
+
+ if (id instanceof InternalCDOIDObject)
+ {
+ CDOID.ObjectType subType = ((InternalCDOIDObject)id).getSubType();
+ int ordinal = subType.ordinal();
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Writing CDOIDObject of subtype {0} ({1})", ordinal, subType); //$NON-NLS-1$
+ }
+
+ // Negated to distinguish between the subtypes and the maintypes.
+ // Note: Added 1 because ordinal start at 0
+ writeByte(-ordinal - 1);
+ }
+ else
+ {
+ CDOID.Type type = id.getType();
+ int ordinal = type.ordinal();
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Writing CDOID of type {0} ({1})", ordinal, type); //$NON-NLS-1$
+ }
+
+ writeByte(ordinal);
+ }
+
+ ((AbstractCDOID)id).write(this);
+ }
+
+ public void writeCDOIDReference(CDOIDReference idReference) throws IOException
+ {
+ idReference.write(this);
+ }
+
+ public void writeCDOIDAndVersion(CDOIDAndVersion idAndVersion) throws IOException
+ {
+ writeCDOID(idAndVersion.getID());
+ writeInt(idAndVersion.getVersion());
+ }
+
+ public void writeCDOIDAndBranch(CDOIDAndBranch idAndBranch) throws IOException
+ {
+ writeCDOID(idAndBranch.getID());
+ writeCDOBranch(idAndBranch.getBranch());
+ }
+
+ public void writeCDORevisionKey(CDORevisionKey revisionKey) throws IOException
+ {
+ writeCDOID(revisionKey.getID());
+ writeCDOBranch(revisionKey.getBranch());
+ writeInt(revisionKey.getVersion());
+ }
+
+ public void writeCDORevision(CDORevision revision, int referenceChunk) throws IOException
+ {
+ if (revision != null)
+ {
+ writeBoolean(true);
+ ((InternalCDORevision)revision).write(this, referenceChunk);
+ }
+ else
+ {
+ writeBoolean(false);
+ }
+ }
+
+ public void writeCDORevisable(CDORevisable revisable) throws IOException
+ {
+ writeCDOBranch(revisable.getBranch());
+ writeInt(revisable.getVersion());
+ writeLong(revisable.getTimeStamp());
+ writeLong(revisable.getRevised());
+ }
+
+ public void writeCDOList(EClass owner, EStructuralFeature feature, CDOList list, int referenceChunk)
+ throws IOException
+ {
+ // TODO Simon: Could most of this stuff be moved into the list?
+ // (only if protected methods of this class don't need to become public)
+ int size = list == null ? 0 : list.size();
+ if (size > 0)
+ {
+ // Need to adjust the referenceChunk in case where we do not have enough value in the list.
+ // Even if the referenceChunk is specified, a provider of data could have override that value.
+ int sizeToLook = referenceChunk == CDORevision.UNCHUNKED ? size : Math.min(referenceChunk, size);
+ for (int i = 0; i < sizeToLook; i++)
+ {
+ Object element = list.get(i, false);
+ if (element == CDORevisionUtil.UNINITIALIZED)
+ {
+ referenceChunk = i;
+ break;
+ }
+ }
+ }
+
+ if (referenceChunk != CDORevision.UNCHUNKED && referenceChunk < size)
+ {
+ // This happens only on server-side
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Writing feature {0}: size={1}, referenceChunk={2}", feature.getName(), size, referenceChunk); //$NON-NLS-1$
+ }
+
+ writeInt(-size);
+ writeInt(referenceChunk);
+ size = referenceChunk;
+ }
+ else
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Writing feature {0}: size={1}", feature.getName(), size); //$NON-NLS-1$
+ }
+
+ writeInt(size);
+ }
+
+ CDOIDProvider idProvider = getIDProvider();
+ boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
+ for (int j = 0; j < size; j++)
+ {
+ Object value = list.get(j, false);
+ EStructuralFeature innerFeature = feature; // Prepare for possible feature map
+ if (isFeatureMap)
+ {
+ Entry entry = (FeatureMap.Entry)value;
+ innerFeature = entry.getEStructuralFeature();
+ value = entry.getValue();
+
+ int featureID = owner.getFeatureID(innerFeature);
+ writeInt(featureID);
+ }
+
+ if (value != null && innerFeature instanceof EReference)
+ {
+ value = idProvider.provideCDOID(value);
+ }
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.trace(" " + value); //$NON-NLS-1$
+ }
+
+ writeCDOFeatureValue(innerFeature, value);
+ }
+ }
+
+ public void writeCDOFeatureValue(EStructuralFeature feature, Object value) throws IOException
+ {
+ CDOType type = CDOModelUtil.getType(feature);
+ type.writeValue(this, value);
+ }
+
+ public void writeCDORevisionDelta(CDORevisionDelta revisionDelta) throws IOException
+ {
+ ((CDORevisionDeltaImpl)revisionDelta).write(this);
+ }
+
+ public void writeCDOFeatureDelta(EClass owner, CDOFeatureDelta featureDelta) throws IOException
+ {
+ ((CDOFeatureDeltaImpl)featureDelta).write(this, owner);
+ }
+
+ public void writeCDORevisionOrPrimitive(Object value) throws IOException
+ {
+ if (value == null)
+ {
+ value = CDOID.NULL;
+ }
+ else if (value instanceof EObject)
+ {
+ value = getIDProvider().provideCDOID(value);
+ }
+ else if (value instanceof CDORevision)
+ {
+ value = ((CDORevision)value).getID();
+ }
+
+ CDOType type = null;
+ if (value instanceof CDOID)
+ {
+ type = CDOType.OBJECT;
+ }
+ else
+ {
+ type = CDOModelUtil.getPrimitiveType(value.getClass());
+ if (type == null)
+ {
+ throw new IllegalArgumentException(MessageFormat.format(
+ Messages.getString("CDODataOutputImpl.6"), value.getClass())); //$NON-NLS-1$
+ }
+ }
+
+ writeCDOType(type);
+ type.writeValue(this, value);
+ }
+
+ public void writeCDORevisionOrPrimitiveOrClassifier(Object value) throws IOException
+ {
+ if (value instanceof EClassifier)
+ {
+ writeBoolean(true);
+ writeCDOClassifierRef((EClass)value);
+ }
+ else
+ {
+ writeBoolean(false);
+ writeCDORevisionOrPrimitive(value);
+ }
+ }
+
+ public CDOPackageRegistry getPackageRegistry()
+ {
+ return null;
+ }
+
+ public CDOIDProvider getIDProvider()
+ {
+ return null;
+ }
+
+ public CDOPermissionProvider getPermissionProvider()
+ {
+ return CDORevision.PERMISSION_PROVIDER;
+ }
+
+ protected StringIO getPackageURICompressor()
+ {
+ return StringIO.DIRECT;
+ }
+}
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 f52ee0bafd..0721bbdbb9 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
@@ -14,15 +14,12 @@
*/
package org.eclipse.emf.cdo.internal.common.revision;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDTemp;
import org.eclipse.emf.cdo.common.model.CDOModelUtil;
import org.eclipse.emf.cdo.common.model.CDOType;
import org.eclipse.emf.cdo.spi.common.revision.BaseCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
-import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EStructuralFeature;
@@ -34,8 +31,6 @@ public class CDORevisionImpl extends BaseCDORevision
{
private Object[] values;
- private transient boolean frozen;
-
public CDORevisionImpl(EClass eClass)
{
super(eClass);
@@ -78,61 +73,14 @@ public class CDORevisionImpl extends BaseCDORevision
}
@Override
- protected Object getValue(int featureIndex)
+ protected Object doGetValue(int featureIndex)
{
return values[featureIndex];
}
@Override
- protected void setValue(int featureIndex, Object value)
+ protected void doSetValue(int featureIndex, Object value)
{
- checkFrozen(featureIndex, value);
values[featureIndex] = value;
}
-
- public void freeze()
- {
- frozen = true;
-
- EStructuralFeature[] features = CDOModelUtil.getAllPersistentFeatures(getEClass());
- for (int i = 0; i < features.length; i++)
- {
- EStructuralFeature feature = features[i];
- if (feature.isMany())
- {
- InternalCDOList list = (InternalCDOList)values[i];
- if (list != null)
- {
- list.freeze();
- }
- }
- }
- }
-
- private void checkFrozen(int featureIndex, Object value)
- {
- if (frozen)
- {
- Object oldValue = values[featureIndex];
-
- // Exception 1: Setting an empty list as the value for an isMany feature, is
- // allowed if the old value is null. This is a case of lazy initialization.
- boolean newIsEmptyList = value instanceof EList<?> && ((EList<?>)value).size() == 0;
- if (newIsEmptyList && oldValue == null)
- {
- return;
- }
-
- // Exception 2a: Replacing a temp ID with a regular ID is allowed (happens during
- // postCommit of new objects)
- // Exception 2b: Replacing a temp ID with another temp ID is also allowed (happens
- // when changes are imported in a PushTx).
- if (oldValue instanceof CDOIDTemp && value instanceof CDOID)
- {
- return;
- }
-
- throw new IllegalStateException("Cannot modify a frozen revision");
- }
- }
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/AbstractCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/AbstractCDORevision.java
index 751821d389..e9d9fba46e 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/AbstractCDORevision.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/AbstractCDORevision.java
@@ -1,204 +1,220 @@
-/*
- * Copyright (c) 2004 - 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
- * Simon McDuff - bug 201266
- * Simon McDuff - bug 212958
- * Simon McDuff - bug 213402
- */
-package org.eclipse.emf.cdo.spi.common.revision;
-
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.model.CDOClassInfo;
-import org.eclipse.emf.cdo.common.model.CDOModelUtil;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionData;
-import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
-import org.eclipse.emf.cdo.internal.common.messages.Messages;
-
-import org.eclipse.net4j.util.ObjectUtil;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EStructuralFeature;
-
-import java.text.MessageFormat;
-
-/**
- * @author Eike Stepper
- * @since 2.0
- */
-public abstract class AbstractCDORevision implements InternalCDORevision
-{
- private CDOClassInfo classInfo;
-
- /**
- * @since 3.0
- */
- protected AbstractCDORevision(EClass eClass)
- {
- if (eClass != null)
- {
- if (eClass.isAbstract())
- {
- throw new IllegalArgumentException(MessageFormat.format(Messages.getString("AbstractCDORevision.0"), eClass)); //$NON-NLS-1$
- }
-
- classInfo = CDOModelUtil.getClassInfo(eClass);
- }
- }
-
- /**
- * @since 3.0
- */
- public CDOClassInfo getClassInfo()
- {
- return classInfo;
- }
-
- public EClass getEClass()
- {
- CDOClassInfo classInfo = getClassInfo();
- if (classInfo != null)
- {
- return classInfo.getEClass();
- }
-
- return null;
- }
-
- public boolean isResourceNode()
- {
- return getClassInfo().isResourceNode();
- }
-
- public boolean isResourceFolder()
- {
- return getClassInfo().isResourceFolder();
- }
-
- public boolean isResource()
- {
- return getClassInfo().isResource();
- }
-
- public CDORevisionData data()
- {
- return this;
- }
-
- public CDORevision revision()
- {
- return this;
- }
-
- /**
- * @since 3.0
- */
- public boolean isHistorical()
- {
- return getRevised() != UNSPECIFIED_DATE;
- }
-
- public boolean isValid(long timeStamp)
- {
- long startTime = getTimeStamp();
- long endTime = getRevised();
- return CDOCommonUtil.isValidTimeStamp(timeStamp, startTime, endTime);
- }
-
- /**
- * @since 4.0
- */
- public boolean isValid(CDOBranchPoint branchPoint)
- {
- return getBranch() == branchPoint.getBranch() && isValid(branchPoint.getTimeStamp());
- }
-
- /**
- * @since 3.0
- */
- public void adjustForCommit(CDOBranch branch, long timeStamp)
- {
- if (ObjectUtil.equals(branch, getBranch()))
- {
- // Same branch, increase version
- setVersion(getVersion() + 1);
- }
- else
- {
- // Different branch, start with v1
- setVersion(FIRST_VERSION);
- }
-
- setBranchPoint(branch.getPoint(timeStamp));
- setRevised(UNSPECIFIED_DATE);
- }
-
- @Override
- public int hashCode()
- {
- return getID().hashCode() ^ getBranch().hashCode() ^ getVersion();
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (obj == this)
- {
- return true;
- }
-
- if (obj instanceof CDORevision)
- {
- CDORevision that = (CDORevision)obj;
- return getID().equals(that.getID()) && getBranch().equals(that.getBranch()) && getVersion() == that.getVersion();
- }
-
- return false;
- }
-
- @Override
- public String toString()
- {
- EClass eClass = getEClass();
- String name = eClass == null ? "Revision" : eClass.getName();
-
- CDOBranch branch = getBranch();
- if (branch == null)
- {
- return name + "@" + getID() + "v" + getVersion();
- }
-
- return name + "@" + getID() + ":" + branch.getID() + "v" + getVersion();
- }
-
- /**
- * @since 3.0
- */
- protected void setClassInfo(CDOClassInfo classInfo)
- {
- this.classInfo = classInfo;
- }
-
- /**
- * @since 3.0
- */
- protected EStructuralFeature[] getAllPersistentFeatures()
- {
- return classInfo.getAllPersistentFeatures();
- }
-
- /**
- * @since 3.0
- */
- protected int getFeatureIndex(EStructuralFeature feature)
- {
- return classInfo.getFeatureIndex(feature);
- }
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Simon McDuff - bug 201266
+ * Simon McDuff - bug 212958
+ * Simon McDuff - bug 213402
+ */
+package org.eclipse.emf.cdo.spi.common.revision;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.model.CDOClassInfo;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionData;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.internal.common.messages.Messages;
+
+import org.eclipse.net4j.util.ObjectUtil;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.text.MessageFormat;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public abstract class AbstractCDORevision implements InternalCDORevision
+{
+ private CDOClassInfo classInfo;
+
+ /**
+ * @since 3.0
+ */
+ protected AbstractCDORevision(EClass eClass)
+ {
+ if (eClass != null)
+ {
+ if (eClass.isAbstract())
+ {
+ throw new IllegalArgumentException(MessageFormat.format(Messages.getString("AbstractCDORevision.0"), eClass)); //$NON-NLS-1$
+ }
+
+ classInfo = CDOModelUtil.getClassInfo(eClass);
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ public CDOClassInfo getClassInfo()
+ {
+ return classInfo;
+ }
+
+ public EClass getEClass()
+ {
+ CDOClassInfo classInfo = getClassInfo();
+ if (classInfo != null)
+ {
+ return classInfo.getEClass();
+ }
+
+ return null;
+ }
+
+ public boolean isResourceNode()
+ {
+ return getClassInfo().isResourceNode();
+ }
+
+ public boolean isResourceFolder()
+ {
+ return getClassInfo().isResourceFolder();
+ }
+
+ public boolean isResource()
+ {
+ return getClassInfo().isResource();
+ }
+
+ public CDORevisionData data()
+ {
+ return this;
+ }
+
+ public CDORevision revision()
+ {
+ return this;
+ }
+
+ /**
+ * @since 3.0
+ */
+ public boolean isHistorical()
+ {
+ return getRevised() != UNSPECIFIED_DATE;
+ }
+
+ public boolean isValid(long timeStamp)
+ {
+ long startTime = getTimeStamp();
+ long endTime = getRevised();
+ return CDOCommonUtil.isValidTimeStamp(timeStamp, startTime, endTime);
+ }
+
+ /**
+ * @since 4.0
+ */
+ public boolean isValid(CDOBranchPoint branchPoint)
+ {
+ return getBranch() == branchPoint.getBranch() && isValid(branchPoint.getTimeStamp());
+ }
+
+ /**
+ * @since 4.1
+ */
+ public boolean isReadable()
+ {
+ return getPermission().isReadable();
+ }
+
+ /**
+ * @since 4.1
+ */
+ public boolean isWritable()
+ {
+ return getPermission().isWritable();
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void adjustForCommit(CDOBranch branch, long timeStamp)
+ {
+ if (ObjectUtil.equals(branch, getBranch()))
+ {
+ // Same branch, increase version
+ setVersion(getVersion() + 1);
+ }
+ else
+ {
+ // Different branch, start with v1
+ setVersion(FIRST_VERSION);
+ }
+
+ setBranchPoint(branch.getPoint(timeStamp));
+ setRevised(UNSPECIFIED_DATE);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return getID().hashCode() ^ getBranch().hashCode() ^ getVersion();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ {
+ return true;
+ }
+
+ if (obj instanceof CDORevision)
+ {
+ CDORevision that = (CDORevision)obj;
+ return getID().equals(that.getID()) && getBranch().equals(that.getBranch()) && getVersion() == that.getVersion();
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString()
+ {
+ EClass eClass = getEClass();
+ String name = eClass == null ? "Revision" : eClass.getName();
+
+ CDOBranch branch = getBranch();
+ if (branch == null)
+ {
+ return name + "@" + getID() + "v" + getVersion();
+ }
+
+ return name + "@" + getID() + ":" + branch.getID() + "v" + getVersion();
+ }
+
+ /**
+ * @since 3.0
+ */
+ protected void setClassInfo(CDOClassInfo classInfo)
+ {
+ this.classInfo = classInfo;
+ }
+
+ /**
+ * @since 3.0
+ */
+ protected EStructuralFeature[] getAllPersistentFeatures()
+ {
+ return classInfo.getAllPersistentFeatures();
+ }
+
+ /**
+ * @since 3.0
+ */
+ protected int getFeatureIndex(EStructuralFeature feature)
+ {
+ return classInfo.getFeatureIndex(feature);
+ }
+}
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 9f86573039..2608cd2f68 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
@@ -1,775 +1,928 @@
-/*
- * Copyright (c) 2004 - 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
- * Simon McDuff - bug 201266
- * Simon McDuff - bug 212958
- * Simon McDuff - bug 213402
- */
-package org.eclipse.emf.cdo.spi.common.revision;
-
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDProvider;
-import org.eclipse.emf.cdo.common.id.CDOIDTemp;
-import org.eclipse.emf.cdo.common.id.CDOIDUtil;
-import org.eclipse.emf.cdo.common.model.CDOClassInfo;
-import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
-import org.eclipse.emf.cdo.common.model.CDOModelUtil;
-import org.eclipse.emf.cdo.common.model.CDOType;
-import org.eclipse.emf.cdo.common.protocol.CDODataInput;
-import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
-import org.eclipse.emf.cdo.common.revision.CDOList;
-import org.eclipse.emf.cdo.common.revision.CDOListFactory;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionData;
-import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
-import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
-import org.eclipse.emf.cdo.internal.common.bundle.OM;
-import org.eclipse.emf.cdo.internal.common.messages.Messages;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionDeltaImpl;
-import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
-
-import org.eclipse.net4j.util.om.trace.ContextTracer;
-import org.eclipse.net4j.util.om.trace.PerfTracer;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EClassifier;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.InternalEObject.EStore;
-import org.eclipse.emf.ecore.util.FeatureMap;
-import org.eclipse.emf.ecore.util.FeatureMap.Entry;
-import org.eclipse.emf.ecore.util.FeatureMapUtil;
-
-import java.io.IOException;
-import java.text.MessageFormat;
-import java.util.Map;
-
-/**
- * @author Eike Stepper
- * @since 3.0
- */
-public abstract class BaseCDORevision extends AbstractCDORevision
-{
- private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, BaseCDORevision.class);
-
- private static final PerfTracer READING = new PerfTracer(OM.PERF_REVISION_READING, BaseCDORevision.class);
-
- private static final PerfTracer WRITING = new PerfTracer(OM.PERF_REVISION_WRITING, BaseCDORevision.class);
-
- private static final byte UNSET = 0;
-
- private static final byte SET_NULL = 1;
-
- private static final byte SET_NOT_NULL = 2;
-
- private CDOID id;
-
- private CDOBranchPoint branchPoint;
-
- private int version;
-
- private long revised;
-
- private CDOID resourceID;
-
- /**
- * On a client, between a local modification and the commit the value of this <i>ID</i> can be an EObject.
- */
- private Object containerID;
-
- private int containingFeatureID;
-
- /**
- * @since 3.0
- */
- public BaseCDORevision(EClass eClass)
- {
- super(eClass);
- if (eClass != null)
- {
- version = UNSPECIFIED_VERSION;
- revised = UNSPECIFIED_DATE;
- resourceID = CDOID.NULL;
- containerID = CDOID.NULL;
- containingFeatureID = 0;
- initValues(getAllPersistentFeatures());
- }
- }
-
- protected BaseCDORevision(BaseCDORevision source)
- {
- super(source.getEClass());
- id = source.id;
- branchPoint = source.branchPoint;
- version = source.version;
- revised = source.revised;
- resourceID = source.resourceID;
- containerID = source.containerID;
- containingFeatureID = source.containingFeatureID;
- }
-
- /**
- * @since 3.0
- */
- public void read(CDODataInput in) throws IOException
- {
- if (READING.isEnabled())
- {
- READING.start(this);
- }
-
- readSystemValues(in);
- readValues(in);
-
- if (READING.isEnabled())
- {
- READING.stop(this);
- }
- }
-
- /**
- * @since 4.0
- */
- protected void readSystemValues(CDODataInput in) throws IOException
- {
- EClassifier classifier = in.readCDOClassifierRefAndResolve();
- CDOClassInfo classInfo = CDOModelUtil.getClassInfo((EClass)classifier);
- setClassInfo(classInfo);
-
- id = in.readCDOID();
- branchPoint = in.readCDOBranchPoint();
- version = in.readInt();
- if (!id.isTemporary())
- {
- revised = in.readLong();
- }
-
- resourceID = in.readCDOID();
- containerID = in.readCDOID();
- containingFeatureID = in.readInt();
-
- if (TRACER.isEnabled())
- {
- TRACER
- .format(
- "Reading revision: ID={0}, className={1}, version={2}, branchPoint={3}, revised={4}, resource={5}, container={6}, featureID={7}", //$NON-NLS-1$
- id, getEClass().getName(), version, branchPoint, revised, resourceID, containerID, containingFeatureID);
- }
- }
-
- /**
- * @since 4.0
- */
- public void write(CDODataOutput out, int referenceChunk) throws IOException
- {
- if (WRITING.isEnabled())
- {
- WRITING.start(this);
- }
-
- writeSystemValues(out);
- writeValues(out, referenceChunk);
-
- if (WRITING.isEnabled())
- {
- WRITING.stop(this);
- }
- }
-
- /**
- * @since 4.0
- */
- protected void writeSystemValues(CDODataOutput out) throws IOException
- {
- EClass eClass = getEClass();
- CDOClassifierRef classRef = new CDOClassifierRef(eClass);
-
- if (TRACER.isEnabled())
- {
- TRACER
- .format(
- "Writing revision: ID={0}, className={1}, version={2}, branchPoint={3}, revised={4}, resource={5}, container={6}, featureID={7}", //$NON-NLS-1$
- id, eClass.getName(), getVersion(), branchPoint, revised, resourceID, containerID, containingFeatureID);
- }
-
- out.writeCDOClassifierRef(classRef);
- out.writeCDOID(id);
- out.writeCDOBranchPoint(branchPoint);
- out.writeInt(getVersion());
- if (!id.isTemporary())
- {
- out.writeLong(revised);
- }
-
- out.writeCDOID(resourceID);
- out.writeCDOID(out.getIDProvider().provideCDOID(containerID));
- out.writeInt(containingFeatureID);
- }
-
- /**
- * @see #write(CDODataOutput, int)
- * @since 3.0
- */
- public void convertEObjects(CDOIDProvider idProvider)
- {
- if (!(containerID instanceof CDOID))
- {
- containerID = idProvider.provideCDOID(containerID);
- }
-
- EStructuralFeature[] features = getAllPersistentFeatures();
- for (int i = 0; i < features.length; i++)
- {
- EStructuralFeature feature = features[i];
- if (feature.isMany())
- {
- CDOList list = getValueAsList(i);
- if (list != null)
- {
- boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
- for (int j = 0; j < list.size(); j++)
- {
- Object value = list.get(j, false);
- EStructuralFeature innerFeature = feature; // Prepare for possible feature map
- if (isFeatureMap)
- {
- Entry entry = (FeatureMap.Entry)value;
- innerFeature = entry.getEStructuralFeature();
- value = entry.getValue();
- }
-
- if (value != null && innerFeature instanceof EReference)
- {
- CDOID newValue = idProvider.provideCDOID(value);
- if (newValue != value)
- {
- list.set(j, newValue);
- }
- }
- }
- }
- }
- else
- {
- checkNoFeatureMap(feature);
- Object value = getValue(i);
- if (value != null && feature instanceof EReference)
- {
- CDOID newValue = idProvider.provideCDOID(value);
- if (newValue != value)
- {
- setValue(i, newValue);
- }
- }
- }
- }
- }
-
- public CDOID getID()
- {
- return id;
- }
-
- public void setID(CDOID id)
- {
- if (CDOIDUtil.isNull(id))
- {
- throw new IllegalArgumentException(Messages.getString("AbstractCDORevision.1")); //$NON-NLS-1$
- }
-
- if (TRACER.isEnabled())
- {
- TRACER.format("Setting ID: {0}", id);
- }
-
- this.id = id;
- }
-
- /**
- * @since 3.0
- */
- public CDOBranch getBranch()
- {
- if (branchPoint == null)
- {
- return null;
- }
-
- return branchPoint.getBranch();
- }
-
- /**
- * @since 3.0
- */
- public long getTimeStamp()
- {
- if (branchPoint == null)
- {
- return UNSPECIFIED_DATE;
- }
-
- return branchPoint.getTimeStamp();
- }
-
- /**
- * @since 3.0
- */
- public void setBranchPoint(CDOBranchPoint branchPoint)
- {
- branchPoint = CDOBranchUtil.copyBranchPoint(branchPoint);
- if (TRACER.isEnabled())
- {
- TRACER.format("Setting branchPoint {0}: {1}", this, branchPoint);
- }
-
- this.branchPoint = branchPoint;
- }
-
- public int getVersion()
- {
- return version;
- }
-
- public void setVersion(int version)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Setting version for {0}: v{1}", this, version);
- }
-
- this.version = version;
- }
-
- public long getRevised()
- {
- return revised;
- }
-
- public void setRevised(long revised)
- {
- long created = branchPoint.getTimeStamp();
- if (revised != UNSPECIFIED_DATE && revised < Math.max(0, created))
- {
- throw new IllegalArgumentException("revision=" + this + ", created=" + CDOCommonUtil.formatTimeStamp(created)
- + ", revised=" + CDOCommonUtil.formatTimeStamp(revised));
- }
-
- if (TRACER.isEnabled())
- {
- TRACER.format("Setting revised {0}: {1}", this, CDOCommonUtil.formatTimeStamp(revised));
- }
-
- this.revised = revised;
- }
-
- public InternalCDORevisionDelta compare(CDORevision origin)
- {
- return new CDORevisionDeltaImpl(origin, this);
- }
-
- public void merge(CDORevisionDelta delta)
- {
- CDORevisionMerger applier = new CDORevisionMerger();
- applier.merge(this, delta);
- }
-
- public CDOID getResourceID()
- {
- return resourceID;
- }
-
- public void setResourceID(CDOID resourceID)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Setting resourceID {0}: {1}", this, resourceID);
- }
-
- this.resourceID = resourceID;
- }
-
- public Object getContainerID()
- {
- return containerID;
- }
-
- public void setContainerID(Object containerID)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Setting containerID {0}: {1}", this, containerID);
- }
-
- this.containerID = containerID;
- }
-
- public int getContainingFeatureID()
- {
- return containingFeatureID;
- }
-
- public void setContainingFeatureID(int containingFeatureID)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Setting containingFeatureID {0}: {1}", this, containingFeatureID);
- }
-
- this.containingFeatureID = containingFeatureID;
- }
-
- public int hashCode(EStructuralFeature feature)
- {
- return getValue(feature).hashCode();
- }
-
- public Object get(EStructuralFeature feature, int index)
- {
- if (feature.isMany() && index != EStore.NO_INDEX)
- {
- CDOList list = getList(feature);
- return list.get(index);
- }
-
- return getValue(feature);
- }
-
- public boolean contains(EStructuralFeature feature, Object value)
- {
- CDOList list = getList(feature);
- return list.contains(value);
- }
-
- public int indexOf(EStructuralFeature feature, Object value)
- {
- CDOList list = getList(feature);
- return list.indexOf(value);
- }
-
- public int lastIndexOf(EStructuralFeature feature, Object value)
- {
- CDOList list = getList(feature);
- return list.lastIndexOf(value);
- }
-
- public boolean isEmpty(EStructuralFeature feature)
- {
- CDOList list = getList(feature);
- return list.isEmpty();
- }
-
- public int size(EStructuralFeature feature)
- {
- CDOList list = getList(feature);
- return list.size();
- }
-
- public Object[] toArray(EStructuralFeature feature)
- {
- if (!feature.isMany())
- {
- throw new IllegalStateException("!feature.isMany()");
- }
-
- CDOList list = getList(feature);
- return list.toArray();
- }
-
- public <T> T[] toArray(EStructuralFeature feature, T[] array)
- {
- if (!feature.isMany())
- {
- throw new IllegalStateException("!feature.isMany()");
- }
-
- CDOList list = getList(feature);
- return list.toArray(array);
- }
-
- public void add(EStructuralFeature feature, int index, Object value)
- {
- CDOList list = getList(feature);
- list.add(index, value);
- }
-
- public void clear(EStructuralFeature feature)
- {
- setValue(feature, null);
- }
-
- public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex)
- {
- CDOList list = getList(feature);
- return list.move(targetIndex, sourceIndex);
- }
-
- public Object remove(EStructuralFeature feature, int index)
- {
- CDOList list = getList(feature);
- return list.remove(index);
- }
-
- public Object set(EStructuralFeature feature, int index, Object value)
- {
- if (feature.isMany())
- {
- CDOList list = getList(feature);
- return list.set(index, value);
- }
-
- return setValue(feature, value);
- }
-
- public void unset(EStructuralFeature feature)
- {
- setValue(feature, null);
- }
-
- /**
- * @since 4.0
- */
- public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Adjusting references for revision {0}", this);
- }
-
- boolean changed = false;
-
- CDOID id1 = (CDOID)referenceAdjuster.adjustReference(resourceID, CDOContainerFeatureDelta.CONTAINER_FEATURE,
- CDOFeatureDelta.NO_INDEX);
- if (id1 != resourceID)
- {
- resourceID = id1;
- changed = true;
- }
-
- Object id2 = referenceAdjuster.adjustReference(containerID, CDOContainerFeatureDelta.CONTAINER_FEATURE,
- CDOFeatureDelta.NO_INDEX);
- if (id2 != containerID)
- {
- containerID = id2;
- changed = true;
- }
-
- EStructuralFeature[] features = getAllPersistentFeatures();
- for (int i = 0; i < features.length; i++)
- {
- EStructuralFeature feature = features[i];
- if (feature instanceof EReference || FeatureMapUtil.isFeatureMap(feature))
- {
- if (feature.isMany())
- {
- InternalCDOList list = (InternalCDOList)getValueAsList(i);
- if (list != null)
- {
- changed |= list.adjustReferences(referenceAdjuster, feature);
- }
- }
- else
- {
- CDOType type = CDOModelUtil.getType(feature);
- Object oldValue = getValue(i);
- Object newValue = type.adjustReferences(referenceAdjuster, oldValue, feature, CDOFeatureDelta.NO_INDEX);
- if (oldValue != newValue) // Just an optimization for NOOP adjusters
- {
- setValue(i, newValue);
- changed = true;
- }
- }
- }
- }
-
- return changed;
- }
-
- public Object getValue(EStructuralFeature feature)
- {
- int featureIndex = getFeatureIndex(feature);
- return getValue(featureIndex);
- }
-
- public Object setValue(EStructuralFeature feature, Object value)
- {
- int featureIndex = getFeatureIndex(feature);
-
- try
- {
- Object old = getValue(featureIndex);
- setValue(featureIndex, value);
- return old;
- }
- catch (ArrayIndexOutOfBoundsException ex)
- {
- throw new IllegalArgumentException(MessageFormat.format(Messages.getString("AbstractCDORevision.20"), feature,
- getClassInfo()), ex);
- }
- }
-
- public CDOList getList(EStructuralFeature feature)
- {
- return getList(feature, 0);
- }
-
- public CDOList getList(EStructuralFeature feature, int size)
- {
- int featureIndex = getFeatureIndex(feature);
- CDOList list = (CDOList)getValue(featureIndex);
- if (list == null && size != -1)
- {
- list = CDOListFactory.DEFAULT.createList(size, 0, 0);
- setValue(featureIndex, list);
- }
-
- return list;
- }
-
- public void setList(EStructuralFeature feature, InternalCDOList list)
- {
- int featureIndex = getFeatureIndex(feature);
- setValue(featureIndex, list);
- }
-
- protected abstract void initValues(EStructuralFeature[] allPersistentFeatures);
-
- protected abstract Object getValue(int featureIndex);
-
- protected abstract void setValue(int featureIndex, Object value);
-
- private CDOList getValueAsList(int i)
- {
- return (CDOList)getValue(i);
- }
-
- private void writeValues(CDODataOutput out, int referenceChunk) throws IOException
- {
- EClass owner = getEClass();
- EStructuralFeature[] features = getAllPersistentFeatures();
- for (int i = 0; i < features.length; i++)
- {
- EStructuralFeature feature = features[i];
- Object value = getValue(i);
- if (value == null)
- {
- // Feature is NOT set
- out.writeByte(UNSET);
- continue;
- }
-
- // Feature IS set
- if (value == CDORevisionData.NIL)
- {
- // Feature IS null
- out.writeByte(SET_NULL);
- continue;
- }
-
- // Feature is NOT null
- out.writeByte(SET_NOT_NULL);
- if (feature.isMany())
- {
- CDOList list = (CDOList)value;
- out.writeCDOList(owner, feature, list, referenceChunk);
- }
- else
- {
- checkNoFeatureMap(feature);
- if (feature instanceof EReference)
- {
- value = out.getIDProvider().provideCDOID(value);
- }
-
- if (TRACER.isEnabled())
- {
- TRACER.format("Writing feature {0}: {1}", feature.getName(), value);
- }
-
- out.writeCDOFeatureValue(feature, value);
- }
- }
- }
-
- private void readValues(CDODataInput in) throws IOException
- {
- EClass owner = getEClass();
- EStructuralFeature[] features = getAllPersistentFeatures();
- initValues(features);
- for (int i = 0; i < features.length; i++)
- {
- Object value;
- EStructuralFeature feature = features[i];
- byte unsetState = in.readByte();
- switch (unsetState)
- {
- case UNSET:
- continue;
-
- case SET_NULL:
- setValue(i, CDORevisionData.NIL);
- continue;
- }
-
- if (feature.isMany())
- {
- value = in.readCDOList(owner, feature);
- }
- else
- {
- value = in.readCDOFeatureValue(feature);
- if (TRACER.isEnabled())
- {
- TRACER.format("Read feature {0}: {1}", feature.getName(), value);
- }
- }
-
- setValue(i, value);
- }
- }
-
- public static void checkNoFeatureMap(EStructuralFeature feature)
- {
- if (FeatureMapUtil.isFeatureMap(feature))
- {
- throw new UnsupportedOperationException("Single-valued feature maps not yet handled");
- }
- }
-
- public static Object remapID(Object value, Map<CDOID, CDOID> idMappings, boolean allowUnmappedTempIDs)
- {
- if (value instanceof CDOID)
- {
- CDOID oldID = (CDOID)value;
- if (!oldID.isNull())
- {
- CDOID newID = idMappings.get(oldID);
- if (newID != null)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Adjusting ID: {0} --> {1}", oldID, newID);
- }
-
- return newID;
- }
-
- if (oldID instanceof CDOIDTemp)
- {
- throw new IllegalStateException(MessageFormat.format(Messages.getString("AbstractCDORevision.2"), oldID));
- }
- }
- }
-
- return value;
- }
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Simon McDuff - bug 201266
+ * Simon McDuff - bug 212958
+ * Simon McDuff - bug 213402
+ */
+package org.eclipse.emf.cdo.spi.common.revision;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDProvider;
+import org.eclipse.emf.cdo.common.id.CDOIDTemp;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.model.CDOClassInfo;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.CDOType;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDOListFactory;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionData;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.security.CDOPermission;
+import org.eclipse.emf.cdo.common.security.CDOPermissionProvider;
+import org.eclipse.emf.cdo.common.security.NoPermissionException;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.internal.common.bundle.OM;
+import org.eclipse.emf.cdo.internal.common.messages.Messages;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionDeltaImpl;
+import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
+
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+import org.eclipse.net4j.util.om.trace.PerfTracer;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.InternalEObject.EStore;
+import org.eclipse.emf.ecore.util.FeatureMap;
+import org.eclipse.emf.ecore.util.FeatureMap.Entry;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public abstract class BaseCDORevision extends AbstractCDORevision
+{
+
+ private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, BaseCDORevision.class);
+
+ private static final PerfTracer READING = new PerfTracer(OM.PERF_REVISION_READING, BaseCDORevision.class);
+
+ private static final PerfTracer WRITING = new PerfTracer(OM.PERF_REVISION_WRITING, BaseCDORevision.class);
+
+ private static final byte UNSET = 0;
+
+ private static final byte SET_NULL = 1;
+
+ private static final byte SET_NOT_NULL = 2;
+
+ private static final byte FROZEN_FLAG = 0x04;
+
+ private static final byte PERMISSION_MASK = 0x03;
+
+ private CDOID id;
+
+ private CDOBranchPoint branchPoint;
+
+ private int version;
+
+ private long revised;
+
+ private CDOID resourceID;
+
+ /**
+ * On a client, between a local modification and the commit the value of this <i>ID</i> can be an EObject.
+ */
+ private Object containerID;
+
+ private int containingFeatureID;
+
+ private transient byte flags = CDOPermission.WRITE.getBits();
+
+ /**
+ * @since 3.0
+ */
+ public BaseCDORevision(EClass eClass)
+ {
+ super(eClass);
+ if (eClass != null)
+ {
+ version = UNSPECIFIED_VERSION;
+ revised = UNSPECIFIED_DATE;
+ resourceID = CDOID.NULL;
+ containerID = CDOID.NULL;
+ containingFeatureID = 0;
+ initValues(getAllPersistentFeatures());
+ }
+
+ flags = CDOPermission.WRITE.getBits();
+ }
+
+ protected BaseCDORevision(BaseCDORevision source)
+ {
+ super(source.getEClass());
+ id = source.id;
+ branchPoint = source.branchPoint;
+ version = source.version;
+ revised = source.revised;
+ resourceID = source.resourceID;
+ containerID = source.containerID;
+ containingFeatureID = source.containingFeatureID;
+ flags = (byte)(source.flags & PERMISSION_MASK);
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void read(CDODataInput in) throws IOException
+ {
+ if (READING.isEnabled())
+ {
+ READING.start(this);
+ }
+
+ readSystemValues(in);
+
+ byte permissionBits = (byte)(in.readByte() & PERMISSION_MASK);
+ if (permissionBits != CDOPermission.NONE.ordinal())
+ {
+ readValues(in);
+ }
+
+ flags = permissionBits;
+
+ if (READING.isEnabled())
+ {
+ READING.stop(this);
+ }
+ }
+
+ /**
+ * @since 4.0
+ */
+ protected void readSystemValues(CDODataInput in) throws IOException
+ {
+ EClassifier classifier = in.readCDOClassifierRefAndResolve();
+ CDOClassInfo classInfo = CDOModelUtil.getClassInfo((EClass)classifier);
+ setClassInfo(classInfo);
+
+ id = in.readCDOID();
+ branchPoint = in.readCDOBranchPoint();
+ version = in.readInt();
+ if (!id.isTemporary())
+ {
+ revised = in.readLong();
+ }
+
+ resourceID = in.readCDOID();
+ containerID = in.readCDOID();
+ containingFeatureID = in.readInt();
+
+ if (TRACER.isEnabled())
+ {
+ TRACER
+ .format(
+ "Reading revision: ID={0}, className={1}, version={2}, branchPoint={3}, revised={4}, resource={5}, container={6}, featureID={7}", //$NON-NLS-1$
+ id, getEClass().getName(), version, branchPoint, revised, resourceID, containerID, containingFeatureID);
+ }
+ }
+
+ /**
+ * @since 4.0
+ */
+ public void write(CDODataOutput out, int referenceChunk) throws IOException
+ {
+ if (WRITING.isEnabled())
+ {
+ WRITING.start(this);
+ }
+
+ writeSystemValues(out);
+
+ CDOPermissionProvider permissionProvider = out.getPermissionProvider();
+ CDOPermission permission = permissionProvider.getPermission(this);
+ out.writeByte(permission.getBits());
+
+ if (permission != CDOPermission.NONE)
+ {
+ writeValues(out, referenceChunk);
+ }
+
+ if (WRITING.isEnabled())
+ {
+ WRITING.stop(this);
+ }
+ }
+
+ /**
+ * @since 4.0
+ */
+ protected void writeSystemValues(CDODataOutput out) throws IOException
+ {
+ EClass eClass = getEClass();
+ CDOClassifierRef classRef = new CDOClassifierRef(eClass);
+
+ if (TRACER.isEnabled())
+ {
+ TRACER
+ .format(
+ "Writing revision: ID={0}, className={1}, version={2}, branchPoint={3}, revised={4}, resource={5}, container={6}, featureID={7}", //$NON-NLS-1$
+ id, eClass.getName(), getVersion(), branchPoint, revised, resourceID, containerID, containingFeatureID);
+ }
+
+ out.writeCDOClassifierRef(classRef);
+ out.writeCDOID(id);
+ out.writeCDOBranchPoint(branchPoint);
+ out.writeInt(getVersion());
+ if (!id.isTemporary())
+ {
+ out.writeLong(revised);
+ }
+
+ out.writeCDOID(resourceID);
+ out.writeCDOID(out.getIDProvider().provideCDOID(containerID));
+ out.writeInt(containingFeatureID);
+ }
+
+ /**
+ * @see #write(CDODataOutput, int)
+ * @since 3.0
+ */
+ public void convertEObjects(CDOIDProvider idProvider)
+ {
+ if (!(containerID instanceof CDOID))
+ {
+ containerID = idProvider.provideCDOID(containerID);
+ }
+
+ EStructuralFeature[] features = getAllPersistentFeatures();
+ for (int i = 0; i < features.length; i++)
+ {
+ EStructuralFeature feature = features[i];
+ if (feature.isMany())
+ {
+ CDOList list = getValueAsList(i);
+ if (list != null)
+ {
+ boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
+ for (int j = 0; j < list.size(); j++)
+ {
+ Object value = list.get(j, false);
+ EStructuralFeature innerFeature = feature; // Prepare for possible feature map
+ if (isFeatureMap)
+ {
+ Entry entry = (FeatureMap.Entry)value;
+ innerFeature = entry.getEStructuralFeature();
+ value = entry.getValue();
+ }
+
+ if (value != null && innerFeature instanceof EReference)
+ {
+ CDOID newValue = idProvider.provideCDOID(value);
+ if (newValue != value)
+ {
+ list.set(j, newValue);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ checkNoFeatureMap(feature);
+ Object value = getValue(i);
+ if (value != null && feature instanceof EReference)
+ {
+ CDOID newValue = idProvider.provideCDOID(value);
+ if (newValue != value)
+ {
+ setValue(i, newValue);
+ }
+ }
+ }
+ }
+ }
+
+ public CDOID getID()
+ {
+ return id;
+ }
+
+ public void setID(CDOID id)
+ {
+ if (CDOIDUtil.isNull(id))
+ {
+ throw new IllegalArgumentException(Messages.getString("AbstractCDORevision.1")); //$NON-NLS-1$
+ }
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting ID: {0}", id);
+ }
+
+ this.id = id;
+ }
+
+ /**
+ * @since 3.0
+ */
+ public CDOBranch getBranch()
+ {
+ if (branchPoint == null)
+ {
+ return null;
+ }
+
+ return branchPoint.getBranch();
+ }
+
+ /**
+ * @since 3.0
+ */
+ public long getTimeStamp()
+ {
+ if (branchPoint == null)
+ {
+ return UNSPECIFIED_DATE;
+ }
+
+ return branchPoint.getTimeStamp();
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void setBranchPoint(CDOBranchPoint branchPoint)
+ {
+ branchPoint = CDOBranchUtil.copyBranchPoint(branchPoint);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting branchPoint {0}: {1}", this, branchPoint);
+ }
+
+ this.branchPoint = branchPoint;
+ }
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(int version)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting version for {0}: v{1}", this, version);
+ }
+
+ this.version = version;
+ }
+
+ public long getRevised()
+ {
+ return revised;
+ }
+
+ public void setRevised(long revised)
+ {
+ long created = branchPoint.getTimeStamp();
+ if (revised != UNSPECIFIED_DATE && revised < Math.max(0, created))
+ {
+ throw new IllegalArgumentException("revision=" + this + ", created=" + CDOCommonUtil.formatTimeStamp(created)
+ + ", revised=" + CDOCommonUtil.formatTimeStamp(revised));
+ }
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting revised {0}: {1}", this, CDOCommonUtil.formatTimeStamp(revised));
+ }
+
+ this.revised = revised;
+ }
+
+ public InternalCDORevisionDelta compare(CDORevision origin)
+ {
+ return new CDORevisionDeltaImpl(origin, this);
+ }
+
+ public void merge(CDORevisionDelta delta)
+ {
+ CDORevisionMerger applier = new CDORevisionMerger();
+ applier.merge(this, delta);
+ }
+
+ public CDOID getResourceID()
+ {
+ return resourceID;
+ }
+
+ public void setResourceID(CDOID resourceID)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting resourceID {0}: {1}", this, resourceID);
+ }
+
+ this.resourceID = resourceID;
+ }
+
+ public Object getContainerID()
+ {
+ return containerID;
+ }
+
+ public void setContainerID(Object containerID)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting containerID {0}: {1}", this, containerID);
+ }
+
+ this.containerID = containerID;
+ }
+
+ public int getContainingFeatureID()
+ {
+ return containingFeatureID;
+ }
+
+ public void setContainingFeatureID(int containingFeatureID)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting containingFeatureID {0}: {1}", this, containingFeatureID);
+ }
+
+ this.containingFeatureID = containingFeatureID;
+ }
+
+ public int hashCode(EStructuralFeature feature)
+ {
+ return getValue(feature).hashCode();
+ }
+
+ public Object get(EStructuralFeature feature, int index)
+ {
+ if (feature.isMany() && index != EStore.NO_INDEX)
+ {
+ CDOList list = getList(feature);
+ return list.get(index);
+ }
+
+ return getValue(feature);
+ }
+
+ public boolean contains(EStructuralFeature feature, Object value)
+ {
+ CDOList list = getList(feature);
+ return list.contains(value);
+ }
+
+ public int indexOf(EStructuralFeature feature, Object value)
+ {
+ CDOList list = getList(feature);
+ return list.indexOf(value);
+ }
+
+ public int lastIndexOf(EStructuralFeature feature, Object value)
+ {
+ CDOList list = getList(feature);
+ return list.lastIndexOf(value);
+ }
+
+ public boolean isEmpty(EStructuralFeature feature)
+ {
+ CDOList list = getList(feature);
+ return list.isEmpty();
+ }
+
+ public int size(EStructuralFeature feature)
+ {
+ CDOList list = getList(feature);
+ return list.size();
+ }
+
+ public Object[] toArray(EStructuralFeature feature)
+ {
+ if (!feature.isMany())
+ {
+ throw new IllegalStateException("!feature.isMany()");
+ }
+
+ CDOList list = getList(feature);
+ return list.toArray();
+ }
+
+ public <T> T[] toArray(EStructuralFeature feature, T[] array)
+ {
+ if (!feature.isMany())
+ {
+ throw new IllegalStateException("!feature.isMany()");
+ }
+
+ CDOList list = getList(feature);
+ return list.toArray(array);
+ }
+
+ public void add(EStructuralFeature feature, int index, Object value)
+ {
+ CDOList list = getList(feature);
+ list.add(index, value);
+ }
+
+ public void clear(EStructuralFeature feature)
+ {
+ setValue(feature, null);
+ }
+
+ public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex)
+ {
+ CDOList list = getList(feature);
+ return list.move(targetIndex, sourceIndex);
+ }
+
+ public Object remove(EStructuralFeature feature, int index)
+ {
+ CDOList list = getList(feature);
+ return list.remove(index);
+ }
+
+ public Object set(EStructuralFeature feature, int index, Object value)
+ {
+ if (feature.isMany())
+ {
+ CDOList list = getList(feature);
+ return list.set(index, value);
+ }
+
+ return setValue(feature, value);
+ }
+
+ public void unset(EStructuralFeature feature)
+ {
+ setValue(feature, null);
+ }
+
+ /**
+ * @since 4.0
+ */
+ public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Adjusting references for revision {0}", this);
+ }
+
+ boolean changed = false;
+
+ CDOID id1 = (CDOID)referenceAdjuster.adjustReference(resourceID, CDOContainerFeatureDelta.CONTAINER_FEATURE,
+ CDOFeatureDelta.NO_INDEX);
+ if (id1 != resourceID)
+ {
+ resourceID = id1;
+ changed = true;
+ }
+
+ Object id2 = referenceAdjuster.adjustReference(containerID, CDOContainerFeatureDelta.CONTAINER_FEATURE,
+ CDOFeatureDelta.NO_INDEX);
+ if (id2 != containerID)
+ {
+ containerID = id2;
+ changed = true;
+ }
+
+ EStructuralFeature[] features = getAllPersistentFeatures();
+ for (int i = 0; i < features.length; i++)
+ {
+ EStructuralFeature feature = features[i];
+ if (feature instanceof EReference || FeatureMapUtil.isFeatureMap(feature))
+ {
+ if (feature.isMany())
+ {
+ InternalCDOList list = (InternalCDOList)getValueAsList(i);
+ if (list != null)
+ {
+ changed |= list.adjustReferences(referenceAdjuster, feature);
+ }
+ }
+ else
+ {
+ CDOType type = CDOModelUtil.getType(feature);
+ Object oldValue = getValue(i);
+ Object newValue = type.adjustReferences(referenceAdjuster, oldValue, feature, CDOFeatureDelta.NO_INDEX);
+ if (oldValue != newValue) // Just an optimization for NOOP adjusters
+ {
+ setValue(i, newValue);
+ changed = true;
+ }
+ }
+ }
+ }
+
+ return changed;
+ }
+
+ public Object getValue(EStructuralFeature feature)
+ {
+ int featureIndex = getFeatureIndex(feature);
+ return getValue(featureIndex);
+ }
+
+ public Object setValue(EStructuralFeature feature, Object value)
+ {
+ int featureIndex = getFeatureIndex(feature);
+
+ try
+ {
+ Object old = getValue(featureIndex);
+ setValue(featureIndex, value);
+ return old;
+ }
+ catch (ArrayIndexOutOfBoundsException ex)
+ {
+ throw new IllegalArgumentException(MessageFormat.format(Messages.getString("AbstractCDORevision.20"), feature,
+ getClassInfo()), ex);
+ }
+ }
+
+ public CDOList getList(EStructuralFeature feature)
+ {
+ return getList(feature, 0);
+ }
+
+ public CDOList getList(EStructuralFeature feature, int size)
+ {
+ int featureIndex = getFeatureIndex(feature);
+ CDOList list = (CDOList)getValue(featureIndex);
+ if (list == null && size != -1)
+ {
+ list = CDOListFactory.DEFAULT.createList(size, 0, 0);
+
+ synchronized (this)
+ {
+ CDOPermission permission = getPermission();
+ if (permission != CDOPermission.WRITE)
+ {
+ setPermission(CDOPermission.WRITE);
+ }
+
+ try
+ {
+ setValue(featureIndex, list);
+ }
+ finally
+ {
+ if (permission != CDOPermission.WRITE)
+ {
+ setPermission(permission);
+ }
+ }
+ }
+ }
+
+ return list;
+ }
+
+ public void setList(EStructuralFeature feature, InternalCDOList list)
+ {
+ int featureIndex = getFeatureIndex(feature);
+ setValue(featureIndex, list);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public CDOPermission getPermission()
+ {
+ return CDOPermission.get(flags & PERMISSION_MASK);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public void setPermission(CDOPermission permission)
+ {
+ flags = (byte)(flags & ~PERMISSION_MASK | permission.getBits() & PERMISSION_MASK);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public void freeze()
+ {
+ flags |= FROZEN_FLAG;
+
+ if (isReadable())
+ {
+ EStructuralFeature[] features = CDOModelUtil.getAllPersistentFeatures(getEClass());
+ for (int i = 0; i < features.length; i++)
+ {
+ EStructuralFeature feature = features[i];
+ if (feature.isMany())
+ {
+ InternalCDOList list = (InternalCDOList)doGetValue(i);
+ if (list != null)
+ {
+ list.freeze();
+ }
+ }
+ }
+ }
+ }
+
+ protected Object getValue(int featureIndex)
+ {
+ checkReadable();
+ return doGetValue(featureIndex);
+ }
+
+ protected void setValue(int featureIndex, Object value)
+ {
+ checkFrozen(featureIndex, value);
+ checkWritable();
+ doSetValue(featureIndex, value);
+ }
+
+ protected abstract void initValues(EStructuralFeature[] allPersistentFeatures);
+
+ /**
+ * @since 4.1
+ */
+ protected abstract Object doGetValue(int featureIndex);
+
+ /**
+ * @since 4.1
+ */
+ protected abstract void doSetValue(int featureIndex, Object value);
+
+ private CDOList getValueAsList(int i)
+ {
+ return (CDOList)getValue(i);
+ }
+
+ private void checkFrozen(int featureIndex, Object value)
+ {
+ if ((flags & FROZEN_FLAG) != 0)
+ {
+ Object oldValue = getValue(featureIndex);
+
+ // Exception 1: Setting an empty list as the value for an isMany feature, is
+ // allowed if the old value is null. This is a case of lazy initialization.
+ boolean newIsEmptyList = value instanceof EList<?> && ((EList<?>)value).size() == 0;
+ if (newIsEmptyList && oldValue == null)
+ {
+ return;
+ }
+
+ // Exception 2a: Replacing a temp ID with a regular ID is allowed (happens during
+ // postCommit of new objects)
+ // Exception 2b: Replacing a temp ID with another temp ID is also allowed (happens
+ // when changes are imported in a PushTx).
+ if (oldValue instanceof CDOIDTemp && value instanceof CDOID)
+ {
+ return;
+ }
+
+ throw new IllegalStateException("Cannot modify a frozen revision");
+ }
+ }
+
+ private void checkReadable()
+ {
+ if (!isReadable())
+ {
+ throw new NoPermissionException(this);
+ }
+ }
+
+ private void checkWritable()
+ {
+ if (!isWritable())
+ {
+ throw new NoPermissionException(this);
+ }
+ }
+
+ private void writeValues(CDODataOutput out, int referenceChunk) throws IOException
+ {
+ EClass owner = getEClass();
+ EStructuralFeature[] features = getAllPersistentFeatures();
+ for (int i = 0; i < features.length; i++)
+ {
+ EStructuralFeature feature = features[i];
+ Object value = getValue(i);
+ if (value == null)
+ {
+ // Feature is NOT set
+ out.writeByte(UNSET);
+ continue;
+ }
+
+ // Feature IS set
+ if (value == CDORevisionData.NIL)
+ {
+ // Feature IS null
+ out.writeByte(SET_NULL);
+ continue;
+ }
+
+ // Feature is NOT null
+ out.writeByte(SET_NOT_NULL);
+ if (feature.isMany())
+ {
+ CDOList list = (CDOList)value;
+ out.writeCDOList(owner, feature, list, referenceChunk);
+ }
+ else
+ {
+ checkNoFeatureMap(feature);
+ if (feature instanceof EReference)
+ {
+ value = out.getIDProvider().provideCDOID(value);
+ }
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Writing feature {0}: {1}", feature.getName(), value);
+ }
+
+ out.writeCDOFeatureValue(feature, value);
+ }
+ }
+ }
+
+ private void readValues(CDODataInput in) throws IOException
+ {
+ EClass owner = getEClass();
+ EStructuralFeature[] features = getAllPersistentFeatures();
+ initValues(features);
+ for (int i = 0; i < features.length; i++)
+ {
+ Object value;
+ EStructuralFeature feature = features[i];
+ byte unsetState = in.readByte();
+ switch (unsetState)
+ {
+ case UNSET:
+ continue;
+
+ case SET_NULL:
+ setValue(i, CDORevisionData.NIL);
+ continue;
+ }
+
+ if (feature.isMany())
+ {
+ value = in.readCDOList(owner, feature);
+ }
+ else
+ {
+ value = in.readCDOFeatureValue(feature);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Read feature {0}: {1}", feature.getName(), value);
+ }
+ }
+
+ setValue(i, value);
+ }
+ }
+
+ public static void checkNoFeatureMap(EStructuralFeature feature)
+ {
+ if (FeatureMapUtil.isFeatureMap(feature))
+ {
+ throw new UnsupportedOperationException("Single-valued feature maps not yet handled");
+ }
+ }
+
+ public static Object remapID(Object value, Map<CDOID, CDOID> idMappings, boolean allowUnmappedTempIDs)
+ {
+ if (value instanceof CDOID)
+ {
+ CDOID oldID = (CDOID)value;
+ if (!oldID.isNull())
+ {
+ CDOID newID = idMappings.get(oldID);
+ if (newID != null)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Adjusting ID: {0} --> {1}", oldID, newID);
+ }
+
+ return newID;
+ }
+
+ if (oldID instanceof CDOIDTemp)
+ {
+ throw new IllegalStateException(MessageFormat.format(Messages.getString("AbstractCDORevision.2"), oldID));
+ }
+ }
+ }
+
+ return value;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevision.java
index 57d87a2b4e..031f06eb0a 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevision.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevision.java
@@ -1,324 +1,357 @@
-/*
- * Copyright (c) 2004 - 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
- * Caspar De Groot - bug 341081
- */
-package org.eclipse.emf.cdo.spi.common.revision;
-
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDProvider;
-import org.eclipse.emf.cdo.common.model.CDOClassInfo;
-import org.eclipse.emf.cdo.common.protocol.CDODataInput;
-import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
-import org.eclipse.emf.cdo.common.revision.CDOList;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionData;
-import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EStructuralFeature;
-
-import java.io.IOException;
-
-/**
- * @author Eike Stepper
- * @since 3.0
- */
-public abstract class DelegatingCDORevision implements InternalCDORevision
-{
- public DelegatingCDORevision()
- {
- }
-
- public abstract InternalCDORevision getDelegate();
-
- /**
- * @since 4.0
- */
- public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster)
- {
- return getDelegate().adjustReferences(referenceAdjuster);
- }
-
- public long getTimeStamp()
- {
- return getDelegate().getTimeStamp();
- }
-
- public CDOBranch getBranch()
- {
- return getDelegate().getBranch();
- }
-
- public boolean isHistorical()
- {
- return getDelegate().isHistorical();
- }
-
- public CDOID getID()
- {
- return getDelegate().getID();
- }
-
- public CDORevision revision()
- {
- return getDelegate().revision();
- }
-
- public CDOID getResourceID()
- {
- return getDelegate().getResourceID();
- }
-
- public Object getContainerID()
- {
- return getDelegate().getContainerID();
- }
-
- public int getContainingFeatureID()
- {
- return getDelegate().getContainingFeatureID();
- }
-
- public Object get(EStructuralFeature feature, int index)
- {
- return getDelegate().get(feature, index);
- }
-
- public EClass getEClass()
- {
- return getDelegate().getEClass();
- }
-
- public int getVersion()
- {
- return getDelegate().getVersion();
- }
-
- public int size(EStructuralFeature feature)
- {
- return getDelegate().size(feature);
- }
-
- public long getRevised()
- {
- return getDelegate().getRevised();
- }
-
- public boolean isEmpty(EStructuralFeature feature)
- {
- return getDelegate().isEmpty(feature);
- }
-
- public boolean isValid(long timeStamp)
- {
- return getDelegate().isValid(timeStamp);
- }
-
- /**
- * @since 4.0
- */
- public boolean isValid(CDOBranchPoint branchPoint)
- {
- return getDelegate().isValid(branchPoint);
- }
-
- /**
- * @since 4.0
- */
- public InternalCDORevision copy()
- {
- return null;
- }
-
- public CDOClassInfo getClassInfo()
- {
- return getDelegate().getClassInfo();
- }
-
- public void setID(CDOID id)
- {
- getDelegate().setID(id);
- }
-
- public boolean contains(EStructuralFeature feature, Object value)
- {
- return getDelegate().contains(feature, value);
- }
-
- public boolean isResourceNode()
- {
- return getDelegate().isResourceNode();
- }
-
- public void setVersion(int version)
- {
- getDelegate().setVersion(version);
- }
-
- public boolean isResourceFolder()
- {
- return getDelegate().isResourceFolder();
- }
-
- public int indexOf(EStructuralFeature feature, Object value)
- {
- return getDelegate().indexOf(feature, value);
- }
-
- public boolean isResource()
- {
- return getDelegate().isResource();
- }
-
- public void setBranchPoint(CDOBranchPoint branchPoint)
- {
- getDelegate().setBranchPoint(branchPoint);
- }
-
- public void adjustForCommit(CDOBranch branch, long timeStamp)
- {
- getDelegate().adjustForCommit(branch, timeStamp);
- }
-
- public CDORevisionData data()
- {
- return getDelegate().data();
- }
-
- public int lastIndexOf(EStructuralFeature feature, Object value)
- {
- return getDelegate().lastIndexOf(feature, value);
- }
-
- public void setRevised(long revised)
- {
- getDelegate().setRevised(revised);
- }
-
- public InternalCDORevisionDelta compare(CDORevision origin)
- {
- return getDelegate().compare(origin);
- }
-
- public void setResourceID(CDOID resourceID)
- {
- getDelegate().setResourceID(resourceID);
- }
-
- public void merge(CDORevisionDelta delta)
- {
- getDelegate().merge(delta);
- }
-
- public <T> T[] toArray(EStructuralFeature feature, T[] array)
- {
- return getDelegate().toArray(feature, array);
- }
-
- public void setContainerID(Object containerID)
- {
- getDelegate().setContainerID(containerID);
- }
-
- public void setContainingFeatureID(int containingFeatureID)
- {
- getDelegate().setContainingFeatureID(containingFeatureID);
- }
-
- public Object[] toArray(EStructuralFeature feature)
- {
- return getDelegate().toArray(feature);
- }
-
- public void add(EStructuralFeature feature, int index, Object value)
- {
- getDelegate().add(feature, index, value);
- }
-
- public int hashCode(EStructuralFeature feature)
- {
- return getDelegate().hashCode(feature);
- }
-
- public void clear(EStructuralFeature feature)
- {
- getDelegate().clear(feature);
- }
-
- public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex)
- {
- return getDelegate().move(feature, targetIndex, sourceIndex);
- }
-
- public Object remove(EStructuralFeature feature, int index)
- {
- return getDelegate().remove(feature, index);
- }
-
- public Object set(EStructuralFeature feature, int index, Object value)
- {
- return getDelegate().set(feature, index, value);
- }
-
- public void unset(EStructuralFeature feature)
- {
- getDelegate().unset(feature);
- }
-
- public Object getValue(EStructuralFeature feature)
- {
- return getDelegate().getValue(feature);
- }
-
- public Object setValue(EStructuralFeature feature, Object value)
- {
- return getDelegate().setValue(feature, value);
- }
-
- public void setList(EStructuralFeature feature, InternalCDOList list)
- {
- getDelegate().setList(feature, list);
- }
-
- public CDOList getList(EStructuralFeature feature)
- {
- return getDelegate().getList(feature);
- }
-
- public CDOList getList(EStructuralFeature feature, int size)
- {
- return getDelegate().getList(feature, size);
- }
-
- public void read(CDODataInput in) throws IOException
- {
- getDelegate().read(in);
- }
-
- public void write(CDODataOutput out, int referenceChunk) throws IOException
- {
- getDelegate().write(out, referenceChunk);
- }
-
- public void convertEObjects(CDOIDProvider oidProvider)
- {
- getDelegate().convertEObjects(oidProvider);
- }
-
- /**
- * @since 4.0
- */
- public void freeze()
- {
- getDelegate().freeze();
- }
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Caspar De Groot - bug 341081
+ */
+package org.eclipse.emf.cdo.spi.common.revision;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDProvider;
+import org.eclipse.emf.cdo.common.model.CDOClassInfo;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionData;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.security.CDOPermission;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.io.IOException;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ */
+public abstract class DelegatingCDORevision implements InternalCDORevision
+{
+ public DelegatingCDORevision()
+ {
+ }
+
+ public abstract InternalCDORevision getDelegate();
+
+ /**
+ * @since 4.0
+ */
+ public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster)
+ {
+ return getDelegate().adjustReferences(referenceAdjuster);
+ }
+
+ public long getTimeStamp()
+ {
+ return getDelegate().getTimeStamp();
+ }
+
+ public CDOBranch getBranch()
+ {
+ return getDelegate().getBranch();
+ }
+
+ public boolean isHistorical()
+ {
+ return getDelegate().isHistorical();
+ }
+
+ public CDOID getID()
+ {
+ return getDelegate().getID();
+ }
+
+ public CDORevision revision()
+ {
+ return getDelegate().revision();
+ }
+
+ public CDOID getResourceID()
+ {
+ return getDelegate().getResourceID();
+ }
+
+ public Object getContainerID()
+ {
+ return getDelegate().getContainerID();
+ }
+
+ public int getContainingFeatureID()
+ {
+ return getDelegate().getContainingFeatureID();
+ }
+
+ public Object get(EStructuralFeature feature, int index)
+ {
+ return getDelegate().get(feature, index);
+ }
+
+ public EClass getEClass()
+ {
+ return getDelegate().getEClass();
+ }
+
+ public int getVersion()
+ {
+ return getDelegate().getVersion();
+ }
+
+ public int size(EStructuralFeature feature)
+ {
+ return getDelegate().size(feature);
+ }
+
+ public long getRevised()
+ {
+ return getDelegate().getRevised();
+ }
+
+ public boolean isEmpty(EStructuralFeature feature)
+ {
+ return getDelegate().isEmpty(feature);
+ }
+
+ public boolean isValid(long timeStamp)
+ {
+ return getDelegate().isValid(timeStamp);
+ }
+
+ /**
+ * @since 4.0
+ */
+ public boolean isValid(CDOBranchPoint branchPoint)
+ {
+ return getDelegate().isValid(branchPoint);
+ }
+
+ /**
+ * @since 4.0
+ */
+ public InternalCDORevision copy()
+ {
+ return null;
+ }
+
+ public CDOClassInfo getClassInfo()
+ {
+ return getDelegate().getClassInfo();
+ }
+
+ public void setID(CDOID id)
+ {
+ getDelegate().setID(id);
+ }
+
+ public boolean contains(EStructuralFeature feature, Object value)
+ {
+ return getDelegate().contains(feature, value);
+ }
+
+ public boolean isResourceNode()
+ {
+ return getDelegate().isResourceNode();
+ }
+
+ public void setVersion(int version)
+ {
+ getDelegate().setVersion(version);
+ }
+
+ public boolean isResourceFolder()
+ {
+ return getDelegate().isResourceFolder();
+ }
+
+ public int indexOf(EStructuralFeature feature, Object value)
+ {
+ return getDelegate().indexOf(feature, value);
+ }
+
+ public boolean isResource()
+ {
+ return getDelegate().isResource();
+ }
+
+ public void setBranchPoint(CDOBranchPoint branchPoint)
+ {
+ getDelegate().setBranchPoint(branchPoint);
+ }
+
+ public void adjustForCommit(CDOBranch branch, long timeStamp)
+ {
+ getDelegate().adjustForCommit(branch, timeStamp);
+ }
+
+ public CDORevisionData data()
+ {
+ return getDelegate().data();
+ }
+
+ public int lastIndexOf(EStructuralFeature feature, Object value)
+ {
+ return getDelegate().lastIndexOf(feature, value);
+ }
+
+ public void setRevised(long revised)
+ {
+ getDelegate().setRevised(revised);
+ }
+
+ public InternalCDORevisionDelta compare(CDORevision origin)
+ {
+ return getDelegate().compare(origin);
+ }
+
+ public void setResourceID(CDOID resourceID)
+ {
+ getDelegate().setResourceID(resourceID);
+ }
+
+ public void merge(CDORevisionDelta delta)
+ {
+ getDelegate().merge(delta);
+ }
+
+ public <T> T[] toArray(EStructuralFeature feature, T[] array)
+ {
+ return getDelegate().toArray(feature, array);
+ }
+
+ public void setContainerID(Object containerID)
+ {
+ getDelegate().setContainerID(containerID);
+ }
+
+ public void setContainingFeatureID(int containingFeatureID)
+ {
+ getDelegate().setContainingFeatureID(containingFeatureID);
+ }
+
+ public Object[] toArray(EStructuralFeature feature)
+ {
+ return getDelegate().toArray(feature);
+ }
+
+ public void add(EStructuralFeature feature, int index, Object value)
+ {
+ getDelegate().add(feature, index, value);
+ }
+
+ public int hashCode(EStructuralFeature feature)
+ {
+ return getDelegate().hashCode(feature);
+ }
+
+ public void clear(EStructuralFeature feature)
+ {
+ getDelegate().clear(feature);
+ }
+
+ public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex)
+ {
+ return getDelegate().move(feature, targetIndex, sourceIndex);
+ }
+
+ public Object remove(EStructuralFeature feature, int index)
+ {
+ return getDelegate().remove(feature, index);
+ }
+
+ public Object set(EStructuralFeature feature, int index, Object value)
+ {
+ return getDelegate().set(feature, index, value);
+ }
+
+ public void unset(EStructuralFeature feature)
+ {
+ getDelegate().unset(feature);
+ }
+
+ public Object getValue(EStructuralFeature feature)
+ {
+ return getDelegate().getValue(feature);
+ }
+
+ public Object setValue(EStructuralFeature feature, Object value)
+ {
+ return getDelegate().setValue(feature, value);
+ }
+
+ public void setList(EStructuralFeature feature, InternalCDOList list)
+ {
+ getDelegate().setList(feature, list);
+ }
+
+ public CDOList getList(EStructuralFeature feature)
+ {
+ return getDelegate().getList(feature);
+ }
+
+ public CDOList getList(EStructuralFeature feature, int size)
+ {
+ return getDelegate().getList(feature, size);
+ }
+
+ public void read(CDODataInput in) throws IOException
+ {
+ getDelegate().read(in);
+ }
+
+ public void write(CDODataOutput out, int referenceChunk) throws IOException
+ {
+ getDelegate().write(out, referenceChunk);
+ }
+
+ public void convertEObjects(CDOIDProvider oidProvider)
+ {
+ getDelegate().convertEObjects(oidProvider);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public CDOPermission getPermission()
+ {
+ return getDelegate().getPermission();
+ }
+
+ /**
+ * @since 4.1
+ */
+ public void setPermission(CDOPermission permission)
+ {
+ getDelegate().setPermission(permission);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public boolean isReadable()
+ {
+ return getDelegate().isReadable();
+ }
+
+ /**
+ * @since 4.1
+ */
+ public boolean isWritable()
+ {
+ return getDelegate().isWritable();
+ }
+
+ /**
+ * @since 4.0
+ */
+ public void freeze()
+ {
+ getDelegate().freeze();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevision.java
index dbce8a0caf..9d646837ba 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevision.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevision.java
@@ -1,121 +1,129 @@
-/*
- * Copyright (c) 2004 - 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
- * Simon McDuff - maintenance
- */
-package org.eclipse.emf.cdo.spi.common.revision;
-
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDProvider;
-import org.eclipse.emf.cdo.common.model.CDOClassInfo;
-import org.eclipse.emf.cdo.common.protocol.CDODataInput;
-import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
-import org.eclipse.emf.cdo.common.revision.CDOList;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionData;
-
-import org.eclipse.emf.ecore.EStructuralFeature;
-
-import java.io.IOException;
-
-/**
- * @author Eike Stepper
- * @since 2.0
- */
-public interface InternalCDORevision extends CDORevision, CDORevisionData, CDOReferenceAdjustable
-{
- /**
- * @since 3.0
- */
- public CDOClassInfo getClassInfo();
-
- public void setID(CDOID id);
-
- public void setVersion(int version);
-
- /**
- * @since 3.0
- */
- public void setBranchPoint(CDOBranchPoint branchPoint);
-
- public void setRevised(long revised);
-
- public void setResourceID(CDOID resourceID);
-
- public void setContainerID(Object containerID);
-
- public void setContainingFeatureID(int containingFeatureID);
-
- /**
- * @since 3.0
- */
- public void adjustForCommit(CDOBranch branch, long timeStamp);
-
- public void add(EStructuralFeature feature, int index, Object value);
-
- public void clear(EStructuralFeature feature);
-
- public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex);
-
- public Object remove(EStructuralFeature feature, int index);
-
- public Object set(EStructuralFeature feature, int index, Object value);
-
- public void unset(EStructuralFeature feature);
-
- /**
- * Should never return {@link InternalCDORevision#NIL}
- */
- public Object getValue(EStructuralFeature feature);
-
- public Object setValue(EStructuralFeature feature, Object value);
-
- public void setList(EStructuralFeature feature, InternalCDOList list);
-
- public CDOList getList(EStructuralFeature feature);
-
- /**
- * @param initialCapacity
- * the initialCapacity of a new list to be created if this revision has no list so far (its size will always
- * be 0), or -1 to skip list creation and return <code>null</code> in this case.
- */
- public CDOList getList(EStructuralFeature feature, int initialCapacity);
-
- /**
- * @since 3.0
- */
- public void read(CDODataInput in) throws IOException;
-
- /**
- * @since 3.0
- */
- public void write(CDODataOutput out, int referenceChunk) throws IOException;
-
- /**
- * @since 3.0
- */
- public void convertEObjects(CDOIDProvider oidProvider);
-
- /**
- * @since 3.0
- */
- public InternalCDORevisionDelta compare(CDORevision origin);
-
- /**
- * @since 3.0
- */
- public InternalCDORevision copy();
-
- /**
- * @since 4.0
- */
- public void freeze();
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Simon McDuff - maintenance
+ */
+package org.eclipse.emf.cdo.spi.common.revision;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDProvider;
+import org.eclipse.emf.cdo.common.model.CDOClassInfo;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionData;
+import org.eclipse.emf.cdo.common.security.CDOPermission;
+
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.io.IOException;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalCDORevision extends CDORevision, CDORevisionData, CDOReferenceAdjustable
+{
+ /**
+ * @since 3.0
+ */
+ public CDOClassInfo getClassInfo();
+
+ public void setID(CDOID id);
+
+ public void setVersion(int version);
+
+ /**
+ * @since 3.0
+ */
+ public void setBranchPoint(CDOBranchPoint branchPoint);
+
+ public void setRevised(long revised);
+
+ public void setResourceID(CDOID resourceID);
+
+ public void setContainerID(Object containerID);
+
+ public void setContainingFeatureID(int containingFeatureID);
+
+ /**
+ * @since 3.0
+ */
+ public void adjustForCommit(CDOBranch branch, long timeStamp);
+
+ public void add(EStructuralFeature feature, int index, Object value);
+
+ public void clear(EStructuralFeature feature);
+
+ public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex);
+
+ public Object remove(EStructuralFeature feature, int index);
+
+ public Object set(EStructuralFeature feature, int index, Object value);
+
+ public void unset(EStructuralFeature feature);
+
+ /**
+ * Should never return {@link InternalCDORevision#NIL}
+ */
+ public Object getValue(EStructuralFeature feature);
+
+ public Object setValue(EStructuralFeature feature, Object value);
+
+ public void setList(EStructuralFeature feature, InternalCDOList list);
+
+ public CDOList getList(EStructuralFeature feature);
+
+ /**
+ * @param initialCapacity
+ * the initialCapacity of a new list to be created if this revision has no list so far (its size will always
+ * be 0), or -1 to skip list creation and return <code>null</code> in this case.
+ */
+ public CDOList getList(EStructuralFeature feature, int initialCapacity);
+
+ /**
+ * @since 3.0
+ */
+ public void read(CDODataInput in) throws IOException;
+
+ /**
+ * @since 3.0
+ */
+ public void write(CDODataOutput out, int referenceChunk) throws IOException;
+
+ /**
+ * @since 3.0
+ */
+ public void convertEObjects(CDOIDProvider oidProvider);
+
+ /**
+ * @since 3.0
+ */
+ public InternalCDORevisionDelta compare(CDORevision origin);
+
+ /**
+ * @since 3.0
+ */
+ public InternalCDORevision copy();
+
+ /**
+ * @since 4.1
+ */
+ public void setPermission(CDOPermission permission);
+
+ /**
+ * @since 4.0
+ */
+ public void freeze();
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/StubCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/StubCDORevision.java
index cc2449465c..72ffca1b96 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/StubCDORevision.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/StubCDORevision.java
@@ -1,269 +1,286 @@
-/*
- * Copyright (c) 2004 - 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.spi.common.revision;
-
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDProvider;
-import org.eclipse.emf.cdo.common.protocol.CDODataInput;
-import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
-import org.eclipse.emf.cdo.common.revision.CDOList;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EStructuralFeature;
-
-import java.io.IOException;
-
-/**
- * @author Eike Stepper
- * @since 3.0
- */
-public class StubCDORevision extends AbstractCDORevision
-{
- public StubCDORevision(EClass eClass)
- {
- super(eClass);
- }
-
- public int compareTo(CDOBranchPoint o)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void setID(CDOID id)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void setVersion(int version)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void setBranchPoint(CDOBranchPoint branchPoint)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void setRevised(long revised)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void setResourceID(CDOID resourceID)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void setContainerID(Object containerID)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void setContainingFeatureID(int containingFeatureID)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void add(EStructuralFeature feature, int index, Object value)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void clear(EStructuralFeature feature)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public Object remove(EStructuralFeature feature, int index)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public Object set(EStructuralFeature feature, int index, Object value)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void unset(EStructuralFeature feature)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public Object getValue(EStructuralFeature feature)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public Object setValue(EStructuralFeature feature, Object value)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void setList(EStructuralFeature feature, InternalCDOList list)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public CDOList getList(EStructuralFeature feature)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public CDOList getList(EStructuralFeature feature, int size)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void read(CDODataInput in) throws IOException
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void write(CDODataOutput out, int referenceChunk) throws IOException
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void convertEObjects(CDOIDProvider oidProvider)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public int getVersion()
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public long getRevised()
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public InternalCDORevisionDelta compare(CDORevision origin)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public void merge(CDORevisionDelta delta)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public InternalCDORevision copy()
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public CDOID getID()
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public CDOBranch getBranch()
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public long getTimeStamp()
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public CDOID getResourceID()
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public Object getContainerID()
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public int getContainingFeatureID()
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public Object get(EStructuralFeature feature, int index)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public int size(EStructuralFeature feature)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public boolean isEmpty(EStructuralFeature feature)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public boolean contains(EStructuralFeature feature, Object value)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public int indexOf(EStructuralFeature feature, Object value)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public int lastIndexOf(EStructuralFeature feature, Object value)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public <T> T[] toArray(EStructuralFeature feature, T[] array)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public Object[] toArray(EStructuralFeature feature)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- public int hashCode(EStructuralFeature feature)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- /**
- * @since 4.0
- */
- public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster)
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- /**
- * @since 4.0
- */
- public void freeze()
- {
- throw new UnsupportedOperationException(getExceptionMessage());
- }
-
- private String getExceptionMessage()
- {
- return "Unsupported operation in " + this;
- }
-}
+/*
+ * Copyright (c) 2004 - 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.spi.common.revision;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDProvider;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.security.CDOPermission;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.io.IOException;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ */
+public class StubCDORevision extends AbstractCDORevision
+{
+ public StubCDORevision(EClass eClass)
+ {
+ super(eClass);
+ }
+
+ public int compareTo(CDOBranchPoint o)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void setID(CDOID id)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void setVersion(int version)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void setBranchPoint(CDOBranchPoint branchPoint)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void setRevised(long revised)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void setResourceID(CDOID resourceID)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void setContainerID(Object containerID)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void setContainingFeatureID(int containingFeatureID)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void add(EStructuralFeature feature, int index, Object value)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void clear(EStructuralFeature feature)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public Object remove(EStructuralFeature feature, int index)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public Object set(EStructuralFeature feature, int index, Object value)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void unset(EStructuralFeature feature)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public Object getValue(EStructuralFeature feature)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public Object setValue(EStructuralFeature feature, Object value)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void setList(EStructuralFeature feature, InternalCDOList list)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public CDOList getList(EStructuralFeature feature)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public CDOList getList(EStructuralFeature feature, int size)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void read(CDODataInput in) throws IOException
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void write(CDODataOutput out, int referenceChunk) throws IOException
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void convertEObjects(CDOIDProvider oidProvider)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public int getVersion()
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public long getRevised()
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public InternalCDORevisionDelta compare(CDORevision origin)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public void merge(CDORevisionDelta delta)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public InternalCDORevision copy()
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public CDOID getID()
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public CDOBranch getBranch()
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public long getTimeStamp()
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public CDOID getResourceID()
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public Object getContainerID()
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public int getContainingFeatureID()
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public Object get(EStructuralFeature feature, int index)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public int size(EStructuralFeature feature)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public boolean isEmpty(EStructuralFeature feature)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public boolean contains(EStructuralFeature feature, Object value)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public int indexOf(EStructuralFeature feature, Object value)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public int lastIndexOf(EStructuralFeature feature, Object value)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public <T> T[] toArray(EStructuralFeature feature, T[] array)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public Object[] toArray(EStructuralFeature feature)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ public int hashCode(EStructuralFeature feature)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ /**
+ * @since 4.0
+ */
+ public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ /**
+ * @since 4.1
+ */
+ public CDOPermission getPermission()
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ /**
+ * @since 4.1
+ */
+ public void setPermission(CDOPermission permission)
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ /**
+ * @since 4.0
+ */
+ public void freeze()
+ {
+ throw new UnsupportedOperationException(getExceptionMessage());
+ }
+
+ private String getExceptionMessage()
+ {
+ return "Unsupported operation in " + this;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate.teneo/src/org/eclipse/emf/cdo/server/hibernate/teneo/CDOEntityMapper.java b/plugins/org.eclipse.emf.cdo.server.hibernate.teneo/src/org/eclipse/emf/cdo/server/hibernate/teneo/CDOEntityMapper.java
index 8f3ee8987c..7ea5549f9f 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate.teneo/src/org/eclipse/emf/cdo/server/hibernate/teneo/CDOEntityMapper.java
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate.teneo/src/org/eclipse/emf/cdo/server/hibernate/teneo/CDOEntityMapper.java
@@ -75,7 +75,10 @@ public class CDOEntityMapper extends EntityMapper
CDOHibernateConstants.CONTAINER_PROPERTY_COLUMN);
final Element versionElement = entityElement.addElement("property"); //$NON-NLS-1$
- versionElement.addAttribute("name", getHbmContext().getVersionColumnName()); //$NON-NLS-1$
+ // add cdo_teneo prefix to prop name prevent name clashes with
+ // efeatures which are accidentally called version
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378050
+ versionElement.addAttribute("name", "cdo_teneo_" + getHbmContext().getVersionColumnName()); //$NON-NLS-1$
versionElement.addElement("meta").addAttribute("attribute", "version").setText("true");
versionElement.addElement("column").addAttribute("name", getHbmContext().getVersionColumnName()); //$NON-NLS-1$//$NON-NLS-2$
versionElement.addAttribute("type", Integer.class.getName()); //$NON-NLS-1$
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndication.java
index 79c49906cc..62b451c2c9 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndication.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndication.java
@@ -1,158 +1,165 @@
-/*
- * Copyright (c) 2004 - 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
- * Simon McDuff - maintenance
- */
-package org.eclipse.emf.cdo.server.internal.net4j.protocol;
-
-import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
-import org.eclipse.emf.cdo.common.commit.CDOCommitInfoManager;
-import org.eclipse.emf.cdo.common.id.CDOIDProvider;
-import org.eclipse.emf.cdo.common.lob.CDOLobStore;
-import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
-import org.eclipse.emf.cdo.common.protocol.CDODataInput;
-import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
-import org.eclipse.emf.cdo.common.revision.CDOListFactory;
-import org.eclipse.emf.cdo.common.revision.CDORevisionFactory;
-import org.eclipse.emf.cdo.internal.common.protocol.CDODataInputImpl;
-import org.eclipse.emf.cdo.internal.common.protocol.CDODataOutputImpl;
-import org.eclipse.emf.cdo.internal.common.revision.CDOListImpl;
-import org.eclipse.emf.cdo.server.IStore;
-import org.eclipse.emf.cdo.spi.server.InternalRepository;
-import org.eclipse.emf.cdo.spi.server.InternalSession;
-
-import org.eclipse.net4j.signal.IndicationWithResponse;
-import org.eclipse.net4j.util.io.ExtendedDataInputStream;
-import org.eclipse.net4j.util.io.ExtendedDataOutputStream;
-import org.eclipse.net4j.util.io.StringIO;
-import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
-
-import java.io.IOException;
-
-/**
- * @author Eike Stepper
- */
-public abstract class CDOServerIndication extends IndicationWithResponse
-{
- public CDOServerIndication(CDOServerProtocol protocol, short signalID)
- {
- super(protocol, signalID);
- }
-
- @Override
- public CDOServerProtocol getProtocol()
- {
- return (CDOServerProtocol)super.getProtocol();
- }
-
- protected InternalSession getSession()
- {
- return getProtocol().getSession();
- }
-
- protected InternalRepository getRepository()
- {
- InternalRepository repository = getSession().getManager().getRepository();
- if (!LifecycleUtil.isActive(repository))
- {
- throw new IllegalStateException("CDORepositoryInfo has been deactivated"); //$NON-NLS-1$
- }
-
- return repository;
- }
-
- protected IStore getStore()
- {
- IStore store = getRepository().getStore();
- if (!LifecycleUtil.isActive(store))
- {
- throw new IllegalStateException("Store has been deactivated"); //$NON-NLS-1$
- }
-
- return store;
- }
-
- @Override
- protected void indicating(ExtendedDataInputStream in) throws Exception
- {
- indicating(new CDODataInputImpl(in)
- {
- @Override
- protected CDOPackageRegistry getPackageRegistry()
- {
- return getRepository().getPackageRegistry();
- }
-
- @Override
- protected StringIO getPackageURICompressor()
- {
- return getProtocol().getPackageURICompressor();
- }
-
- @Override
- protected CDOBranchManager getBranchManager()
- {
- return getRepository().getBranchManager();
- }
-
- @Override
- protected CDOCommitInfoManager getCommitInfoManager()
- {
- return getRepository().getCommitInfoManager();
- }
-
- @Override
- protected CDORevisionFactory getRevisionFactory()
- {
- return getRepository().getRevisionManager().getFactory();
- }
-
- @Override
- protected CDOLobStore getLobStore()
- {
- return null; // Not used on server
- }
-
- @Override
- protected CDOListFactory getListFactory()
- {
- return CDOListImpl.FACTORY;
- }
- });
- }
-
- @Override
- protected void responding(ExtendedDataOutputStream out) throws Exception
- {
- responding(new CDODataOutputImpl(out)
- {
- @Override
- public CDOPackageRegistry getPackageRegistry()
- {
- return getRepository().getPackageRegistry();
- }
-
- @Override
- public CDOIDProvider getIDProvider()
- {
- return getSession();
- }
-
- @Override
- protected StringIO getPackageURICompressor()
- {
- return getProtocol().getPackageURICompressor();
- }
- });
- }
-
- protected abstract void indicating(CDODataInput in) throws IOException;
-
- protected abstract void responding(CDODataOutput out) throws IOException;
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Simon McDuff - maintenance
+ */
+package org.eclipse.emf.cdo.server.internal.net4j.protocol;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoManager;
+import org.eclipse.emf.cdo.common.id.CDOIDProvider;
+import org.eclipse.emf.cdo.common.lob.CDOLobStore;
+import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDOListFactory;
+import org.eclipse.emf.cdo.common.revision.CDORevisionFactory;
+import org.eclipse.emf.cdo.common.security.CDOPermissionProvider;
+import org.eclipse.emf.cdo.internal.common.protocol.CDODataInputImpl;
+import org.eclipse.emf.cdo.internal.common.protocol.CDODataOutputImpl;
+import org.eclipse.emf.cdo.internal.common.revision.CDOListImpl;
+import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+
+import org.eclipse.net4j.signal.IndicationWithResponse;
+import org.eclipse.net4j.util.io.ExtendedDataInputStream;
+import org.eclipse.net4j.util.io.ExtendedDataOutputStream;
+import org.eclipse.net4j.util.io.StringIO;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+
+import java.io.IOException;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class CDOServerIndication extends IndicationWithResponse
+{
+ public CDOServerIndication(CDOServerProtocol protocol, short signalID)
+ {
+ super(protocol, signalID);
+ }
+
+ @Override
+ public CDOServerProtocol getProtocol()
+ {
+ return (CDOServerProtocol)super.getProtocol();
+ }
+
+ protected InternalSession getSession()
+ {
+ return getProtocol().getSession();
+ }
+
+ protected InternalRepository getRepository()
+ {
+ InternalRepository repository = getSession().getManager().getRepository();
+ if (!LifecycleUtil.isActive(repository))
+ {
+ throw new IllegalStateException("CDORepositoryInfo has been deactivated"); //$NON-NLS-1$
+ }
+
+ return repository;
+ }
+
+ protected IStore getStore()
+ {
+ IStore store = getRepository().getStore();
+ if (!LifecycleUtil.isActive(store))
+ {
+ throw new IllegalStateException("Store has been deactivated"); //$NON-NLS-1$
+ }
+
+ return store;
+ }
+
+ @Override
+ protected void indicating(ExtendedDataInputStream in) throws Exception
+ {
+ indicating(new CDODataInputImpl(in)
+ {
+ @Override
+ protected CDOPackageRegistry getPackageRegistry()
+ {
+ return getRepository().getPackageRegistry();
+ }
+
+ @Override
+ protected StringIO getPackageURICompressor()
+ {
+ return getProtocol().getPackageURICompressor();
+ }
+
+ @Override
+ protected CDOBranchManager getBranchManager()
+ {
+ return getRepository().getBranchManager();
+ }
+
+ @Override
+ protected CDOCommitInfoManager getCommitInfoManager()
+ {
+ return getRepository().getCommitInfoManager();
+ }
+
+ @Override
+ protected CDORevisionFactory getRevisionFactory()
+ {
+ return getRepository().getRevisionManager().getFactory();
+ }
+
+ @Override
+ protected CDOLobStore getLobStore()
+ {
+ return null; // Not used on server
+ }
+
+ @Override
+ protected CDOListFactory getListFactory()
+ {
+ return CDOListImpl.FACTORY;
+ }
+ });
+ }
+
+ @Override
+ protected void responding(ExtendedDataOutputStream out) throws Exception
+ {
+ responding(new CDODataOutputImpl(out)
+ {
+ @Override
+ public CDOPackageRegistry getPackageRegistry()
+ {
+ return getRepository().getPackageRegistry();
+ }
+
+ @Override
+ public CDOIDProvider getIDProvider()
+ {
+ return getSession();
+ }
+
+ @Override
+ public CDOPermissionProvider getPermissionProvider()
+ {
+ return getSession();
+ }
+
+ @Override
+ protected StringIO getPackageURICompressor()
+ {
+ return getProtocol().getPackageURICompressor();
+ }
+ });
+ }
+
+ protected abstract void indicating(CDODataInput in) throws IOException;
+
+ protected abstract void responding(CDODataOutput out) throws IOException;
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java
index 1ab78243d4..707cc9639e 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java
@@ -1,579 +1,592 @@
-/*
- * Copyright (c) 2004 - 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
- * Simon McDuff - bug 201266
- * Simon McDuff - bug 230832
- * Simon McDuff - bug 233490
- * Simon McDuff - bug 213402
- */
-package org.eclipse.emf.cdo.internal.server;
-
-import org.eclipse.emf.cdo.common.CDOCommonRepository;
-import org.eclipse.emf.cdo.common.CDOCommonSession;
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDUtil;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.common.model.CDOModelUtil;
-import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
-import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
-import org.eclipse.emf.cdo.internal.common.commit.DelegatingCommitInfo;
-import org.eclipse.emf.cdo.server.IView;
-import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
-import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
-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.ISessionProtocol;
-import org.eclipse.emf.cdo.spi.server.InternalSession;
-import org.eclipse.emf.cdo.spi.server.InternalSessionManager;
-import org.eclipse.emf.cdo.spi.server.InternalTransaction;
-import org.eclipse.emf.cdo.spi.server.InternalView;
-
-import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
-import org.eclipse.net4j.util.collection.IndexedList;
-import org.eclipse.net4j.util.container.Container;
-import org.eclipse.net4j.util.event.EventUtil;
-import org.eclipse.net4j.util.event.IListener;
-import org.eclipse.net4j.util.lifecycle.ILifecycle;
-import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
-import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
-import org.eclipse.net4j.util.om.log.OMLogger;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
-
-import java.text.MessageFormat;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * @author Eike Stepper
- */
-public class Session extends Container<IView> implements InternalSession
-{
- private InternalSessionManager manager;
-
- private ISessionProtocol protocol;
-
- private int sessionID;
-
- private String userID;
-
- private boolean passiveUpdateEnabled = true;
-
- private PassiveUpdateMode passiveUpdateMode = PassiveUpdateMode.INVALIDATIONS;
-
- private LockNotificationMode lockNotificationMode = LockNotificationMode.IF_REQUIRED_BY_VIEWS;
-
- private long lastUpdateTime;
-
- @ExcludeFromDump
- private Object lastUpdateTimeLock = new Object();
-
- private ConcurrentMap<Integer, InternalView> views = new ConcurrentHashMap<Integer, InternalView>();
-
- private AtomicInteger lastTempViewID = new AtomicInteger();
-
- @ExcludeFromDump
- private IListener protocolListener = new LifecycleEventAdapter()
- {
- @Override
- protected void onDeactivated(ILifecycle lifecycle)
- {
- deactivate();
- }
- };
-
- private boolean subscribed;
-
- /**
- * @since 2.0
- */
- public Session(InternalSessionManager manager, ISessionProtocol protocol, int sessionID, String userID)
- {
- this.manager = manager;
- this.protocol = protocol;
- this.sessionID = sessionID;
- this.userID = userID;
-
- EventUtil.addListener(protocol, protocolListener);
- activate();
- }
-
- /**
- * @since 2.0
- */
- public Options options()
- {
- return this;
- }
-
- /**
- * @since 2.0
- */
- public CDOCommonSession getContainer()
- {
- return this;
- }
-
- public InternalSessionManager getManager()
- {
- return manager;
- }
-
- public ISessionProtocol getProtocol()
- {
- return protocol;
- }
-
- public int getSessionID()
- {
- return sessionID;
- }
-
- /**
- * @since 2.0
- */
- public String getUserID()
- {
- return userID;
- }
-
- /**
- * @since 2.0
- */
- public boolean isSubscribed()
- {
- return subscribed;
- }
-
- /**
- * @since 2.0
- */
- public void setSubscribed(boolean subscribed)
- {
- checkActive();
- if (this.subscribed != subscribed)
- {
- this.subscribed = subscribed;
- byte opcode = subscribed ? CDOProtocolConstants.REMOTE_SESSION_SUBSCRIBED
- : CDOProtocolConstants.REMOTE_SESSION_UNSUBSCRIBED;
- manager.sendRemoteSessionNotification(this, opcode);
- }
- }
-
- /**
- * @since 2.0
- */
- public boolean isPassiveUpdateEnabled()
- {
- return passiveUpdateEnabled;
- }
-
- /**
- * @since 2.0
- */
- public void setPassiveUpdateEnabled(boolean passiveUpdateEnabled)
- {
- checkActive();
- this.passiveUpdateEnabled = passiveUpdateEnabled;
- }
-
- public PassiveUpdateMode getPassiveUpdateMode()
- {
- return passiveUpdateMode;
- }
-
- public void setPassiveUpdateMode(PassiveUpdateMode passiveUpdateMode)
- {
- checkActive();
- checkArg(passiveUpdateMode, "passiveUpdateMode");
- this.passiveUpdateMode = passiveUpdateMode;
- }
-
- public LockNotificationMode getLockNotificationMode()
- {
- return lockNotificationMode;
- }
-
- public void setLockNotificationMode(LockNotificationMode lockNotificationMode)
- {
- checkActive();
- checkArg(lockNotificationMode, "lockNotificationMode");
- this.lockNotificationMode = lockNotificationMode;
- }
-
- public long getLastUpdateTime()
- {
- synchronized (lastUpdateTimeLock)
- {
- return lastUpdateTime;
- }
- }
-
- public InternalView[] getElements()
- {
- checkActive();
- return getViews();
- }
-
- @Override
- public boolean isEmpty()
- {
- checkActive();
- return views.isEmpty();
- }
-
- public InternalView[] getViews()
- {
- checkActive();
- return getViewsArray();
- }
-
- private InternalView[] getViewsArray()
- {
- return views.values().toArray(new InternalView[views.size()]);
- }
-
- public InternalView getView(int viewID)
- {
- checkActive();
- return views.get(viewID);
- }
-
- /**
- * @since 2.0
- */
- public InternalView openView(int viewID, CDOBranchPoint branchPoint)
- {
- checkActive();
- if (viewID == TEMP_VIEW_ID)
- {
- viewID = -lastTempViewID.incrementAndGet();
- }
-
- InternalView view = new View(this, viewID, branchPoint);
- view.activate();
- addView(view);
- return view;
- }
-
- /**
- * @since 2.0
- */
- public InternalTransaction openTransaction(int viewID, CDOBranchPoint branchPoint)
- {
- checkActive();
- if (viewID == TEMP_VIEW_ID)
- {
- viewID = -lastTempViewID.incrementAndGet();
- }
-
- InternalTransaction transaction = new Transaction(this, viewID, branchPoint);
- transaction.activate();
- addView(transaction);
- return transaction;
- }
-
- private void addView(InternalView view)
- {
- checkActive();
- int viewID = view.getViewID();
- views.put(viewID, view);
- fireElementAddedEvent(view);
- }
-
- /**
- * @since 2.0
- */
- public void viewClosed(InternalView view)
- {
- int viewID = view.getViewID();
- if (views.remove(viewID) == view)
- {
- view.doClose();
- fireElementRemovedEvent(view);
- }
- }
-
- /**
- * TODO I can't see how recursion is controlled/limited
- *
- * @since 2.0
- */
- public void collectContainedRevisions(InternalCDORevision revision, CDOBranchPoint branchPoint, int referenceChunk,
- Set<CDOID> revisions, List<CDORevision> additionalRevisions)
- {
- InternalCDORevisionManager revisionManager = getManager().getRepository().getRevisionManager();
- EClass eClass = revision.getEClass();
- EStructuralFeature[] features = CDOModelUtil.getAllPersistentFeatures(eClass);
- for (int i = 0; i < features.length; i++)
- {
- EStructuralFeature feature = features[i];
- // TODO Clarify feature maps
- if (feature instanceof EReference && !feature.isMany() && ((EReference)feature).isContainment())
- {
- Object value = revision.getValue(feature);
- if (value instanceof CDOID)
- {
- CDOID id = (CDOID)value;
- if (!CDOIDUtil.isNull(id) && !revisions.contains(id))
- {
- InternalCDORevision containedRevision = revisionManager.getRevision(id, branchPoint, referenceChunk,
- CDORevision.DEPTH_NONE, true);
- revisions.add(id);
- additionalRevisions.add(containedRevision);
-
- // Recurse
- collectContainedRevisions(containedRevision, branchPoint, referenceChunk, revisions, additionalRevisions);
- }
- }
- }
- }
- }
-
- public CDOID provideCDOID(Object idObject)
- {
- return (CDOID)idObject;
- }
-
- public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType)
- throws Exception
- {
- if (protocol != null)
- {
- protocol.sendRepositoryTypeNotification(oldType, newType);
- }
- }
-
- @Deprecated
- public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState)
- throws Exception
- {
- sendRepositoryStateNotification(oldState, newState, null);
- }
-
- public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
- CDOID rootResourceID) throws Exception
- {
- if (protocol != null)
- {
- protocol.sendRepositoryStateNotification(oldState, newState, rootResourceID);
- }
- }
-
- public void sendBranchNotification(InternalCDOBranch branch) throws Exception
- {
- if (protocol != null)
- {
- protocol.sendBranchNotification(branch);
- }
- }
-
- public void sendCommitNotification(final CDOCommitInfo commitInfo) throws Exception
- {
- if (protocol == null)
- {
- return;
- }
-
- if (!isPassiveUpdateEnabled())
- {
- return;
- }
-
- final InternalView[] views = getViews();
- protocol.sendCommitNotification(new DelegatingCommitInfo()
- {
- private final PassiveUpdateMode passiveUpdateMode = getPassiveUpdateMode();
-
- private final boolean additions = passiveUpdateMode == PassiveUpdateMode.ADDITIONS;
-
- private final boolean changes = passiveUpdateMode == PassiveUpdateMode.CHANGES;
-
- @Override
- protected CDOCommitInfo getDelegate()
- {
- return commitInfo;
- }
-
- @Override
- public List<CDOIDAndVersion> getNewObjects()
- {
- final List<CDOIDAndVersion> newObjects = super.getNewObjects();
- return new IndexedList<CDOIDAndVersion>()
- {
- @Override
- public CDOIDAndVersion get(int index)
- {
- // The following will always be a CDORevision!
- CDOIDAndVersion newObject = newObjects.get(index);
- if (additions)
- {
- // Return full revisions if not in INVALIDATION mode
- return newObject;
- }
-
- // Prevent sending whole revisions by copying the id and version
- return CDOIDUtil.createIDAndVersion(newObject);
- }
-
- @Override
- public int size()
- {
- return newObjects.size();
- }
- };
- }
-
- @Override
- public List<CDORevisionKey> getChangedObjects()
- {
- final List<CDORevisionKey> changedObjects = super.getChangedObjects();
- return new IndexedList<CDORevisionKey>()
- {
- @Override
- public CDORevisionKey get(int index)
- {
- // The following will always be a CDORevisionDelta!
- CDORevisionKey changedObject = changedObjects.get(index);
- if (changes || additions || hasSubscription(changedObject.getID(), views))
- {
- return changedObject;
- }
-
- // Prevent sending whole revisions by copying the id and version
- return CDORevisionUtil.copyRevisionKey(changedObject);
- }
-
- @Override
- public int size()
- {
- return changedObjects.size();
- }
- };
- }
- });
-
- synchronized (lastUpdateTimeLock)
- {
- lastUpdateTime = commitInfo.getTimeStamp();
- }
- }
-
- public void sendLockNotification(CDOLockChangeInfo lockChangeInfo) throws Exception
- {
- if (protocol != null)
- {
- if (options().getLockNotificationMode() == LockNotificationMode.ALWAYS)
- {
- protocol.sendLockNotification(lockChangeInfo);
- return;
- }
-
- if (options().getLockNotificationMode() == LockNotificationMode.IF_REQUIRED_BY_VIEWS)
- {
- // If this session has one (or more) views configured for this branch,
- // only then do we send the lockChangeInfo.
- for (InternalView view : getViews())
- {
- if (view.options().isLockNotificationEnabled())
- {
- CDOBranch affectedBranch = lockChangeInfo.getBranch();
- if (view.getBranch().equals(affectedBranch) || affectedBranch == null)
- {
- protocol.sendLockNotification(lockChangeInfo);
- break;
- }
- }
- }
- }
- }
- }
-
- private boolean hasSubscription(CDOID id, InternalView[] views)
- {
- for (InternalView view : views)
- {
- if (view.hasSubscription(id))
- {
- return true;
- }
- }
-
- return false;
- }
-
- public void sendRemoteSessionNotification(InternalSession sender, byte opcode) throws Exception
- {
- if (protocol != null)
- {
- protocol.sendRemoteSessionNotification(sender, opcode);
- }
- }
-
- public void sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message) throws Exception
- {
- if (protocol != null)
- {
- protocol.sendRemoteMessageNotification(sender, message);
- }
- }
-
- @Override
- public String toString()
- {
- return MessageFormat.format("Session[{0}]", sessionID); //$NON-NLS-1$
- }
-
- /**
- * @since 2.0
- */
- public void close()
- {
- LifecycleUtil.deactivate(this, OMLogger.Level.DEBUG);
- }
-
- /**
- * @since 2.0
- */
- public boolean isClosed()
- {
- return !isActive();
- }
-
- @Override
- protected void doDeactivate() throws Exception
- {
- EventUtil.removeListener(protocol, protocolListener);
- protocolListener = null;
-
- LifecycleUtil.deactivate(protocol, OMLogger.Level.DEBUG);
- protocol = null;
-
- for (IView view : getViewsArray())
- {
- view.close();
- }
-
- views = null;
- manager.sessionClosed(this);
- manager = null;
- super.doDeactivate();
- }
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Simon McDuff - bug 201266
+ * Simon McDuff - bug 230832
+ * Simon McDuff - bug 233490
+ * Simon McDuff - bug 213402
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.CDOCommonSession;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.security.CDOPermission;
+import org.eclipse.emf.cdo.internal.common.commit.DelegatingCommitInfo;
+import org.eclipse.emf.cdo.server.IPermissionManager;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+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.ISessionProtocol;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalSessionManager;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.collection.IndexedList;
+import org.eclipse.net4j.util.container.Container;
+import org.eclipse.net4j.util.event.EventUtil;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.lifecycle.ILifecycle;
+import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.log.OMLogger;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Eike Stepper
+ */
+public class Session extends Container<IView> implements InternalSession
+{
+ private InternalSessionManager manager;
+
+ private ISessionProtocol protocol;
+
+ private int sessionID;
+
+ private String userID;
+
+ private boolean passiveUpdateEnabled = true;
+
+ private PassiveUpdateMode passiveUpdateMode = PassiveUpdateMode.INVALIDATIONS;
+
+ private LockNotificationMode lockNotificationMode = LockNotificationMode.IF_REQUIRED_BY_VIEWS;
+
+ private long lastUpdateTime;
+
+ @ExcludeFromDump
+ private Object lastUpdateTimeLock = new Object();
+
+ private ConcurrentMap<Integer, InternalView> views = new ConcurrentHashMap<Integer, InternalView>();
+
+ private AtomicInteger lastTempViewID = new AtomicInteger();
+
+ @ExcludeFromDump
+ private IListener protocolListener = new LifecycleEventAdapter()
+ {
+ @Override
+ protected void onDeactivated(ILifecycle lifecycle)
+ {
+ deactivate();
+ }
+ };
+
+ private boolean subscribed;
+
+ /**
+ * @since 2.0
+ */
+ public Session(InternalSessionManager manager, ISessionProtocol protocol, int sessionID, String userID)
+ {
+ this.manager = manager;
+ this.protocol = protocol;
+ this.sessionID = sessionID;
+ this.userID = userID;
+
+ EventUtil.addListener(protocol, protocolListener);
+ activate();
+ }
+
+ /**
+ * @since 2.0
+ */
+ public Options options()
+ {
+ return this;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public CDOCommonSession getContainer()
+ {
+ return this;
+ }
+
+ public InternalSessionManager getManager()
+ {
+ return manager;
+ }
+
+ public ISessionProtocol getProtocol()
+ {
+ return protocol;
+ }
+
+ public int getSessionID()
+ {
+ return sessionID;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public String getUserID()
+ {
+ return userID;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public boolean isSubscribed()
+ {
+ return subscribed;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void setSubscribed(boolean subscribed)
+ {
+ checkActive();
+ if (this.subscribed != subscribed)
+ {
+ this.subscribed = subscribed;
+ byte opcode = subscribed ? CDOProtocolConstants.REMOTE_SESSION_SUBSCRIBED
+ : CDOProtocolConstants.REMOTE_SESSION_UNSUBSCRIBED;
+ manager.sendRemoteSessionNotification(this, opcode);
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public boolean isPassiveUpdateEnabled()
+ {
+ return passiveUpdateEnabled;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void setPassiveUpdateEnabled(boolean passiveUpdateEnabled)
+ {
+ checkActive();
+ this.passiveUpdateEnabled = passiveUpdateEnabled;
+ }
+
+ public PassiveUpdateMode getPassiveUpdateMode()
+ {
+ return passiveUpdateMode;
+ }
+
+ public void setPassiveUpdateMode(PassiveUpdateMode passiveUpdateMode)
+ {
+ checkActive();
+ checkArg(passiveUpdateMode, "passiveUpdateMode");
+ this.passiveUpdateMode = passiveUpdateMode;
+ }
+
+ public LockNotificationMode getLockNotificationMode()
+ {
+ return lockNotificationMode;
+ }
+
+ public void setLockNotificationMode(LockNotificationMode lockNotificationMode)
+ {
+ checkActive();
+ checkArg(lockNotificationMode, "lockNotificationMode");
+ this.lockNotificationMode = lockNotificationMode;
+ }
+
+ public long getLastUpdateTime()
+ {
+ synchronized (lastUpdateTimeLock)
+ {
+ return lastUpdateTime;
+ }
+ }
+
+ public InternalView[] getElements()
+ {
+ checkActive();
+ return getViews();
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ checkActive();
+ return views.isEmpty();
+ }
+
+ public InternalView[] getViews()
+ {
+ checkActive();
+ return getViewsArray();
+ }
+
+ private InternalView[] getViewsArray()
+ {
+ return views.values().toArray(new InternalView[views.size()]);
+ }
+
+ public InternalView getView(int viewID)
+ {
+ checkActive();
+ return views.get(viewID);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public InternalView openView(int viewID, CDOBranchPoint branchPoint)
+ {
+ checkActive();
+ if (viewID == TEMP_VIEW_ID)
+ {
+ viewID = -lastTempViewID.incrementAndGet();
+ }
+
+ InternalView view = new View(this, viewID, branchPoint);
+ view.activate();
+ addView(view);
+ return view;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public InternalTransaction openTransaction(int viewID, CDOBranchPoint branchPoint)
+ {
+ checkActive();
+ if (viewID == TEMP_VIEW_ID)
+ {
+ viewID = -lastTempViewID.incrementAndGet();
+ }
+
+ InternalTransaction transaction = new Transaction(this, viewID, branchPoint);
+ transaction.activate();
+ addView(transaction);
+ return transaction;
+ }
+
+ private void addView(InternalView view)
+ {
+ checkActive();
+ int viewID = view.getViewID();
+ views.put(viewID, view);
+ fireElementAddedEvent(view);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void viewClosed(InternalView view)
+ {
+ int viewID = view.getViewID();
+ if (views.remove(viewID) == view)
+ {
+ view.doClose();
+ fireElementRemovedEvent(view);
+ }
+ }
+
+ /**
+ * TODO I can't see how recursion is controlled/limited
+ *
+ * @since 2.0
+ */
+ public void collectContainedRevisions(InternalCDORevision revision, CDOBranchPoint branchPoint, int referenceChunk,
+ Set<CDOID> revisions, List<CDORevision> additionalRevisions)
+ {
+ InternalCDORevisionManager revisionManager = getManager().getRepository().getRevisionManager();
+ EClass eClass = revision.getEClass();
+ EStructuralFeature[] features = CDOModelUtil.getAllPersistentFeatures(eClass);
+ for (int i = 0; i < features.length; i++)
+ {
+ EStructuralFeature feature = features[i];
+ // TODO Clarify feature maps
+ if (feature instanceof EReference && !feature.isMany() && ((EReference)feature).isContainment())
+ {
+ Object value = revision.getValue(feature);
+ if (value instanceof CDOID)
+ {
+ CDOID id = (CDOID)value;
+ if (!CDOIDUtil.isNull(id) && !revisions.contains(id))
+ {
+ InternalCDORevision containedRevision = revisionManager.getRevision(id, branchPoint, referenceChunk,
+ CDORevision.DEPTH_NONE, true);
+ revisions.add(id);
+ additionalRevisions.add(containedRevision);
+
+ // Recurse
+ collectContainedRevisions(containedRevision, branchPoint, referenceChunk, revisions, additionalRevisions);
+ }
+ }
+ }
+ }
+ }
+
+ public CDOID provideCDOID(Object idObject)
+ {
+ return (CDOID)idObject;
+ }
+
+ public CDOPermission getPermission(Object protectableObject)
+ {
+ IPermissionManager permissionManager = manager.getPermissionManager();
+ if (permissionManager != null)
+ {
+ return permissionManager.getPermission(protectableObject, userID);
+ }
+
+ return CDORevision.PERMISSION_PROVIDER.getPermission(protectableObject);
+ }
+
+ public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType)
+ throws Exception
+ {
+ if (protocol != null)
+ {
+ protocol.sendRepositoryTypeNotification(oldType, newType);
+ }
+ }
+
+ @Deprecated
+ public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState)
+ throws Exception
+ {
+ sendRepositoryStateNotification(oldState, newState, null);
+ }
+
+ public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
+ CDOID rootResourceID) throws Exception
+ {
+ if (protocol != null)
+ {
+ protocol.sendRepositoryStateNotification(oldState, newState, rootResourceID);
+ }
+ }
+
+ public void sendBranchNotification(InternalCDOBranch branch) throws Exception
+ {
+ if (protocol != null)
+ {
+ protocol.sendBranchNotification(branch);
+ }
+ }
+
+ public void sendCommitNotification(final CDOCommitInfo commitInfo) throws Exception
+ {
+ if (protocol == null)
+ {
+ return;
+ }
+
+ if (!isPassiveUpdateEnabled())
+ {
+ return;
+ }
+
+ final InternalView[] views = getViews();
+ protocol.sendCommitNotification(new DelegatingCommitInfo()
+ {
+ private final PassiveUpdateMode passiveUpdateMode = getPassiveUpdateMode();
+
+ private final boolean additions = passiveUpdateMode == PassiveUpdateMode.ADDITIONS;
+
+ private final boolean changes = passiveUpdateMode == PassiveUpdateMode.CHANGES;
+
+ @Override
+ protected CDOCommitInfo getDelegate()
+ {
+ return commitInfo;
+ }
+
+ @Override
+ public List<CDOIDAndVersion> getNewObjects()
+ {
+ final List<CDOIDAndVersion> newObjects = super.getNewObjects();
+ return new IndexedList<CDOIDAndVersion>()
+ {
+ @Override
+ public CDOIDAndVersion get(int index)
+ {
+ // The following will always be a CDORevision!
+ CDOIDAndVersion newObject = newObjects.get(index);
+ if (additions)
+ {
+ // Return full revisions if not in INVALIDATION mode
+ return newObject;
+ }
+
+ // Prevent sending whole revisions by copying the id and version
+ return CDOIDUtil.createIDAndVersion(newObject);
+ }
+
+ @Override
+ public int size()
+ {
+ return newObjects.size();
+ }
+ };
+ }
+
+ @Override
+ public List<CDORevisionKey> getChangedObjects()
+ {
+ final List<CDORevisionKey> changedObjects = super.getChangedObjects();
+ return new IndexedList<CDORevisionKey>()
+ {
+ @Override
+ public CDORevisionKey get(int index)
+ {
+ // The following will always be a CDORevisionDelta!
+ CDORevisionKey changedObject = changedObjects.get(index);
+ if (changes || additions || hasSubscription(changedObject.getID(), views))
+ {
+ return changedObject;
+ }
+
+ // Prevent sending whole revisions by copying the id and version
+ return CDORevisionUtil.copyRevisionKey(changedObject);
+ }
+
+ @Override
+ public int size()
+ {
+ return changedObjects.size();
+ }
+ };
+ }
+ });
+
+ synchronized (lastUpdateTimeLock)
+ {
+ lastUpdateTime = commitInfo.getTimeStamp();
+ }
+ }
+
+ public void sendLockNotification(CDOLockChangeInfo lockChangeInfo) throws Exception
+ {
+ if (protocol != null)
+ {
+ if (options().getLockNotificationMode() == LockNotificationMode.ALWAYS)
+ {
+ protocol.sendLockNotification(lockChangeInfo);
+ return;
+ }
+
+ if (options().getLockNotificationMode() == LockNotificationMode.IF_REQUIRED_BY_VIEWS)
+ {
+ // If this session has one (or more) views configured for this branch,
+ // only then do we send the lockChangeInfo.
+ for (InternalView view : getViews())
+ {
+ if (view.options().isLockNotificationEnabled())
+ {
+ CDOBranch affectedBranch = lockChangeInfo.getBranch();
+ if (view.getBranch().equals(affectedBranch) || affectedBranch == null)
+ {
+ protocol.sendLockNotification(lockChangeInfo);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private boolean hasSubscription(CDOID id, InternalView[] views)
+ {
+ for (InternalView view : views)
+ {
+ if (view.hasSubscription(id))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void sendRemoteSessionNotification(InternalSession sender, byte opcode) throws Exception
+ {
+ if (protocol != null)
+ {
+ protocol.sendRemoteSessionNotification(sender, opcode);
+ }
+ }
+
+ public void sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message) throws Exception
+ {
+ if (protocol != null)
+ {
+ protocol.sendRemoteMessageNotification(sender, message);
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return MessageFormat.format("Session[{0}]", sessionID); //$NON-NLS-1$
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void close()
+ {
+ LifecycleUtil.deactivate(this, OMLogger.Level.DEBUG);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public boolean isClosed()
+ {
+ return !isActive();
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ EventUtil.removeListener(protocol, protocolListener);
+ protocolListener = null;
+
+ LifecycleUtil.deactivate(protocol, OMLogger.Level.DEBUG);
+ protocol = null;
+
+ for (IView view : getViewsArray())
+ {
+ view.close();
+ }
+
+ views = null;
+ manager.sessionClosed(this);
+ manager = null;
+ super.doDeactivate();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java
index eaa096cf8a..4aeb40e0c9 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java
@@ -20,6 +20,7 @@ import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.IPermissionManager;
import org.eclipse.emf.cdo.server.ISession;
import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult;
@@ -72,6 +73,8 @@ public class SessionManager extends Container<ISession> implements InternalSessi
private IUserManager userManager;
+ private IPermissionManager permissionManager;
+
private final Map<Integer, InternalSession> sessions = new HashMap<Integer, InternalSession>();
private final AtomicInteger lastSessionID = new AtomicInteger();
@@ -165,6 +168,16 @@ public class SessionManager extends Container<ISession> implements InternalSessi
this.userManager = userManager;
}
+ public IPermissionManager getPermissionManager()
+ {
+ return permissionManager;
+ }
+
+ public void setPermissionManager(IPermissionManager permissionManager)
+ {
+ this.permissionManager = permissionManager;
+ }
+
public InternalSession[] getSessions()
{
synchronized (sessions)
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 7781a0dac6..2644eae146 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
@@ -1,1500 +1,1506 @@
-/*
- * Copyright (c) 2004 - 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:
- * Simon McDuff - initial API and implementation
- * Eike Stepper - maintenance
- * Martin Fluegge - maintenance, bug 318518
- */
-package org.eclipse.emf.cdo.internal.server;
-
-import org.eclipse.emf.cdo.common.CDOCommonRepository.IDGenerationLocation;
-import org.eclipse.emf.cdo.common.branch.CDOBranch;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.commit.CDOCommitData;
-import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDObject;
-import org.eclipse.emf.cdo.common.id.CDOIDReference;
-import org.eclipse.emf.cdo.common.id.CDOIDUtil;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
-import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
-import org.eclipse.emf.cdo.common.lock.CDOLockState;
-import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
-import org.eclipse.emf.cdo.common.model.CDOModelUtil;
-import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
-import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
-import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
-import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
-import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
-import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
-import org.eclipse.emf.cdo.internal.common.commit.CDOCommitDataImpl;
-import org.eclipse.emf.cdo.internal.common.commit.FailureCommitInfo;
-import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl;
-import org.eclipse.emf.cdo.internal.server.bundle.OM;
-import org.eclipse.emf.cdo.server.ContainmentCycleDetectedException;
-import org.eclipse.emf.cdo.server.IStoreAccessor;
-import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
-import org.eclipse.emf.cdo.server.IView;
-import org.eclipse.emf.cdo.server.StoreThreadLocal;
-import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
-import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
-import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
-import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
-import org.eclipse.emf.cdo.spi.common.revision.CDOFeatureDeltaVisitorImpl;
-import org.eclipse.emf.cdo.spi.common.revision.CDOIDMapper;
-import org.eclipse.emf.cdo.spi.common.revision.CDOReferenceAdjuster;
-import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
-import org.eclipse.emf.cdo.spi.common.revision.StubCDORevision;
-import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
-import org.eclipse.emf.cdo.spi.server.InternalLockManager;
-import org.eclipse.emf.cdo.spi.server.InternalRepository;
-import org.eclipse.emf.cdo.spi.server.InternalSession;
-import org.eclipse.emf.cdo.spi.server.InternalTransaction;
-
-import org.eclipse.net4j.util.CheckUtil;
-import org.eclipse.net4j.util.ObjectUtil;
-import org.eclipse.net4j.util.StringUtil;
-import org.eclipse.net4j.util.collection.IndexedList;
-import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
-import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
-import org.eclipse.net4j.util.io.ExtendedDataInputStream;
-import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
-import org.eclipse.net4j.util.om.monitor.Monitor;
-import org.eclipse.net4j.util.om.monitor.OMMonitor;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EPackage;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.ConcurrentModificationException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * @author Simon McDuff
- * @since 2.0
- */
-public class TransactionCommitContext implements InternalCommitContext
-{
- private static final InternalCDORevision DETACHED = new StubCDORevision(null);
-
- private final InternalTransaction transaction;
-
- private InternalRepository repository;
-
- private InternalCDORevisionManager revisionManager;
-
- private InternalLockManager lockManager;
-
- private InternalCDOPackageRegistry repositoryPackageRegistry;
-
- private boolean packageRegistryLocked;
-
- private TransactionPackageRegistry packageRegistry;
-
- private IStoreAccessor accessor;
-
- private long timeStamp = CDORevision.UNSPECIFIED_DATE;
-
- private long previousTimeStamp = CDORevision.UNSPECIFIED_DATE;
-
- private String commitComment;
-
- private InternalCDOPackageUnit[] newPackageUnits = new InternalCDOPackageUnit[0];
-
- private CDOLockState[] locksOnNewObjects = new CDOLockState[0];
-
- private InternalCDORevision[] newObjects = new InternalCDORevision[0];
-
- private InternalCDORevisionDelta[] dirtyObjectDeltas = new InternalCDORevisionDelta[0];
-
- private CDOID[] detachedObjects = new CDOID[0];
-
- private Map<CDOID, EClass> detachedObjectTypes;
-
- private InternalCDORevision[] dirtyObjects = new InternalCDORevision[0];
-
- private InternalCDORevision[] cachedDetachedRevisions = new InternalCDORevision[0];
-
- private Map<CDOID, InternalCDORevision> cachedRevisions;
-
- private Set<Object> lockedObjects = new HashSet<Object>();
-
- private List<CDOID> lockedTargets;
-
- private ConcurrentMap<CDOID, CDOID> idMappings = new ConcurrentHashMap<CDOID, CDOID>();
-
- private CDOReferenceAdjuster idMapper = new CDOIDMapper(idMappings);
-
- private String rollbackMessage;
-
- private List<CDOIDReference> xRefs;
-
- private List<LockState<Object, IView>> postCommitLockStates;
-
- private boolean ensuringReferentialIntegrity;
-
- private boolean autoReleaseLocksEnabled;
-
- private ExtendedDataInputStream lobs;
-
- public TransactionCommitContext(InternalTransaction transaction)
- {
- this.transaction = transaction;
-
- repository = transaction.getRepository();
- revisionManager = repository.getRevisionManager();
- lockManager = repository.getLockingManager();
- ensuringReferentialIntegrity = repository.isEnsuringReferentialIntegrity();
-
- repositoryPackageRegistry = repository.getPackageRegistry(false);
- packageRegistry = new TransactionPackageRegistry(repositoryPackageRegistry);
- packageRegistry.activate();
- }
-
- public InternalTransaction getTransaction()
- {
- return transaction;
- }
-
- public CDOBranchPoint getBranchPoint()
- {
- return transaction.getBranch().getPoint(timeStamp);
- }
-
- public String getUserID()
- {
- return transaction.getSession().getUserID();
- }
-
- public String getCommitComment()
- {
- return commitComment;
- }
-
- public boolean isAutoReleaseLocksEnabled()
- {
- return autoReleaseLocksEnabled;
- }
-
- public String getRollbackMessage()
- {
- return rollbackMessage;
- }
-
- public List<CDOIDReference> getXRefs()
- {
- return xRefs;
- }
-
- public InternalCDOPackageRegistry getPackageRegistry()
- {
- return packageRegistry;
- }
-
- public InternalCDOPackageUnit[] getNewPackageUnits()
- {
- return newPackageUnits;
- }
-
- public CDOLockState[] getLocksOnNewObjects()
- {
- return locksOnNewObjects;
- }
-
- public InternalCDORevision[] getNewObjects()
- {
- return newObjects;
- }
-
- public InternalCDORevision[] getDirtyObjects()
- {
- return dirtyObjects;
- }
-
- public CDOID[] getDetachedObjects()
- {
- return detachedObjects;
- }
-
- public Map<CDOID, EClass> getDetachedObjectTypes()
- {
- return detachedObjectTypes;
- }
-
- public InternalCDORevision[] getDetachedRevisions()
- {
- // This array can contain null values as they only come from the cache!
- for (InternalCDORevision cachedDetachedRevision : cachedDetachedRevisions)
- {
- if (cachedDetachedRevision == null)
- {
- throw new AssertionError("Detached revisions are incomplete");
- }
- }
-
- return cachedDetachedRevisions;
- }
-
- public InternalCDORevisionDelta[] getDirtyObjectDeltas()
- {
- return dirtyObjectDeltas;
- }
-
- public CDORevision getRevision(CDOID id)
- {
- if (cachedRevisions == null)
- {
- cachedRevisions = cacheRevisions();
- }
-
- // Try "after state"
- InternalCDORevision revision = cachedRevisions.get(id);
- if (revision == DETACHED)
- {
- return null;
- }
-
- if (revision != null)
- {
- return revision;
- }
-
- // Fall back to "before state"
- return transaction.getRevision(id);
- }
-
- private Map<CDOID, InternalCDORevision> cacheRevisions()
- {
- Map<CDOID, InternalCDORevision> cache = new HashMap<CDOID, InternalCDORevision>();
- if (newObjects != null)
- {
- for (int i = 0; i < newObjects.length; i++)
- {
- InternalCDORevision revision = newObjects[i];
- cache.put(revision.getID(), revision);
- }
- }
-
- if (dirtyObjects != null)
- {
- for (int i = 0; i < dirtyObjects.length; i++)
- {
- InternalCDORevision revision = dirtyObjects[i];
- cache.put(revision.getID(), revision);
- }
- }
-
- if (detachedObjects != null)
- {
- for (int i = 0; i < detachedObjects.length; i++)
- {
- cache.put(detachedObjects[i], DETACHED);
- }
- }
-
- return cache;
- }
-
- public Map<CDOID, CDOID> getIDMappings()
- {
- return Collections.unmodifiableMap(idMappings);
- }
-
- public void addIDMapping(CDOID oldID, CDOID newID)
- {
- if (CDOIDUtil.isNull(newID) || newID.isTemporary())
- {
- throw new IllegalStateException("newID=" + newID); //$NON-NLS-1$
- }
-
- CDOID previousMapping = idMappings.putIfAbsent(oldID, newID);
- if (previousMapping != null)
- {
- throw new IllegalStateException("previousMapping != null"); //$NON-NLS-1$
- }
- }
-
- public void applyIDMappings(OMMonitor monitor)
- {
- boolean mapIDs = !idMappings.isEmpty();
- monitor.begin(1 + (mapIDs ? newObjects.length + dirtyObjects.length + dirtyObjectDeltas.length : 0));
-
- try
- {
- if (mapIDs)
- {
- applyIDMappings(newObjects, monitor.fork(newObjects.length));
- applyIDMappings(dirtyObjects, monitor.fork(dirtyObjects.length));
- for (CDORevisionDelta dirtyObjectDelta : dirtyObjectDeltas)
- {
- ((InternalCDORevisionDelta)dirtyObjectDelta).adjustReferences(idMapper);
- monitor.worked();
- }
- }
-
- // Do not notify handlers before the IDs are fully mapped!
- notifyBeforeCommitting(monitor);
- }
- finally
- {
- monitor.done();
- }
- }
-
- protected void notifyBeforeCommitting(OMMonitor monitor)
- {
- repository.notifyWriteAccessHandlers(transaction, this, true, monitor.fork());
- }
-
- public void preWrite()
- {
- // Allocate a store writer
- accessor = repository.getStore().getWriter(transaction);
-
- // Make the store writer available in a ThreadLocal variable
- StoreThreadLocal.setAccessor(accessor);
- StoreThreadLocal.setCommitContext(this);
- }
-
- public void setNewPackageUnits(InternalCDOPackageUnit[] newPackageUnits)
- {
- this.newPackageUnits = newPackageUnits;
- }
-
- public void setLocksOnNewObjects(CDOLockState[] locksOnNewObjects)
- {
- this.locksOnNewObjects = locksOnNewObjects;
- }
-
- public void setNewObjects(InternalCDORevision[] newObjects)
- {
- this.newObjects = newObjects;
- }
-
- public void setDirtyObjectDeltas(InternalCDORevisionDelta[] dirtyObjectDeltas)
- {
- this.dirtyObjectDeltas = dirtyObjectDeltas;
- }
-
- public void setDetachedObjects(CDOID[] detachedObjects)
- {
- this.detachedObjects = detachedObjects;
- }
-
- public void setDetachedObjectTypes(Map<CDOID, EClass> detachedObjectTypes)
- {
- this.detachedObjectTypes = detachedObjectTypes;
- }
-
- public void setAutoReleaseLocksEnabled(boolean on)
- {
- autoReleaseLocksEnabled = on;
- }
-
- public void setCommitComment(String commitComment)
- {
- this.commitComment = commitComment;
- }
-
- public ExtendedDataInputStream getLobs()
- {
- return lobs;
- }
-
- public void setLobs(ExtendedDataInputStream in)
- {
- lobs = in;
- }
-
- /**
- * @since 2.0
- */
- public void write(OMMonitor monitor)
- {
- try
- {
- monitor.begin(107);
- dirtyObjects = new InternalCDORevision[dirtyObjectDeltas.length];
-
- if (newPackageUnits.length != 0)
- {
- repository.getPackageRegistryCommitLock().acquire();
- packageRegistryLocked = true;
-
- List<InternalCDOPackageUnit> noDuplicates = new ArrayList<InternalCDOPackageUnit>();
- for (InternalCDOPackageUnit newPackageUnit : newPackageUnits)
- {
- String id = newPackageUnit.getID();
- if (!repositoryPackageRegistry.containsKey(id))
- {
- noDuplicates.add(newPackageUnit);
- }
- }
-
- int newSize = noDuplicates.size();
- if (newPackageUnits.length != newSize)
- {
- newPackageUnits = noDuplicates.toArray(new InternalCDOPackageUnit[newSize]);
- }
- }
-
- lockObjects(); // Can take long and must come before setTimeStamp()
- monitor.worked();
-
- setTimeStamp(monitor.fork());
-
- adjustForCommit();
- monitor.worked();
-
- computeDirtyObjects(monitor.fork());
-
- checkXRefs();
- monitor.worked();
-
- if (rollbackMessage == null)
- {
- detachObjects(monitor.fork());
- accessor.write(this, monitor.fork(100));
- }
- }
- catch (Throwable t)
- {
- handleException(t);
- }
- finally
- {
- finishMonitor(monitor);
- }
- }
-
- public void commit(OMMonitor monitor)
- {
- try
- {
- monitor.begin(101);
- accessor.commit(monitor.fork(100));
- updateInfraStructure(monitor.fork());
-
- // Bugzilla 297940
- repository.endCommit(timeStamp);
- }
- catch (Throwable ex)
- {
- handleException(ex);
- }
- finally
- {
- finishMonitor(monitor);
- }
- }
-
- public List<LockState<Object, IView>> getPostCommmitLockStates()
- {
- return postCommitLockStates;
- }
-
- private void handleException(Throwable ex)
- {
- try
- {
- OM.LOG.error(ex);
- String storeClass = repository.getStore().getClass().getSimpleName();
- rollback("Rollback in " + storeClass + ": " + StringUtil.formatException(ex)); //$NON-NLS-1$ //$NON-NLS-2$
- }
- catch (Exception ex1)
- {
- if (rollbackMessage == null)
- {
- rollbackMessage = ex1.getMessage();
- }
-
- try
- {
- OM.LOG.error(ex1);
- }
- catch (Exception ignore)
- {
- }
- }
- }
-
- private void finishMonitor(OMMonitor monitor)
- {
- try
- {
- monitor.done();
- }
- catch (Exception ex)
- {
- try
- {
- OM.LOG.warn(ex);
- }
- catch (Exception ignore)
- {
- }
- }
- }
-
- private void setTimeStamp(OMMonitor mmonitor)
- {
- long[] times = createTimeStamp(mmonitor); // Could throw an exception
- timeStamp = times[0];
- previousTimeStamp = times[1];
- CheckUtil.checkState(timeStamp != CDOBranchPoint.UNSPECIFIED_DATE, "Commit timestamp must not be 0");
- }
-
- protected long[] createTimeStamp(OMMonitor monitor)
- {
- return repository.createCommitTimeStamp(monitor);
- }
-
- protected long getTimeStamp()
- {
- return timeStamp;
- }
-
- protected void setTimeStamp(long timeStamp)
- {
- repository.forceCommitTimeStamp(timeStamp, new Monitor());
- this.timeStamp = timeStamp;
- }
-
- public long getPreviousTimeStamp()
- {
- return previousTimeStamp;
- }
-
- public void postCommit(boolean success)
- {
- if (packageRegistryLocked)
- {
- repository.getPackageRegistryCommitLock().release();
- }
-
- try
- {
- InternalSession sender = transaction.getSession();
- CDOCommitInfo commitInfo = success ? createCommitInfo() : createFailureCommitInfo();
-
- repository.sendCommitNotification(sender, commitInfo);
- }
- catch (Exception ex)
- {
- OM.LOG.warn("A problem occured while notifying other sessions", ex);
- }
- finally
- {
- StoreThreadLocal.release();
- accessor = null;
- lockedTargets = null;
-
- if (packageRegistry != null)
- {
- packageRegistry.deactivate();
- packageRegistry = null;
- }
- }
- }
-
- public CDOCommitInfo createCommitInfo()
- {
- CDOBranch branch = transaction.getBranch();
- String userID = transaction.getSession().getUserID();
- CDOCommitData commitData = createCommitData();
-
- InternalCDOCommitInfoManager commitInfoManager = repository.getCommitInfoManager();
- return commitInfoManager.createCommitInfo(branch, timeStamp, previousTimeStamp, userID, commitComment, commitData);
- }
-
- public CDOCommitInfo createFailureCommitInfo()
- {
- return new FailureCommitInfo(timeStamp, previousTimeStamp);
- }
-
- private CDOCommitData createCommitData()
- {
- List<CDOPackageUnit> newPackageUnitsCollection = new IndexedList.ArrayBacked<CDOPackageUnit>()
- {
- @Override
- protected CDOPackageUnit[] getArray()
- {
- return newPackageUnits;
- }
- };
-
- List<CDOIDAndVersion> newObjectsCollection = new IndexedList.ArrayBacked<CDOIDAndVersion>()
- {
- @Override
- protected CDOIDAndVersion[] getArray()
- {
- return newObjects;
- }
- };
-
- List<CDORevisionKey> changedObjectsCollection = new IndexedList.ArrayBacked<CDORevisionKey>()
- {
- @Override
- protected CDORevisionKey[] getArray()
- {
- return dirtyObjectDeltas;
- }
- };
-
- List<CDOIDAndVersion> detachedObjectsCollection = new IndexedList<CDOIDAndVersion>()
- {
- @Override
- public CDOIDAndVersion get(int i)
- {
- if (cachedDetachedRevisions[i] != null)
- {
- return cachedDetachedRevisions[i];
- }
-
- return CDOIDUtil.createIDAndVersion(detachedObjects[i], CDORevision.UNSPECIFIED_VERSION);
- }
-
- @Override
- public int size()
- {
- return detachedObjects.length;
- }
- };
-
- return new CDOCommitDataImpl(newPackageUnitsCollection, newObjectsCollection, changedObjectsCollection,
- detachedObjectsCollection);
- }
-
- protected void adjustForCommit()
- {
- for (InternalCDOPackageUnit newPackageUnit : newPackageUnits)
- {
- newPackageUnit.setTimeStamp(timeStamp);
- }
-
- CDOBranch branch = transaction.getBranch();
- for (InternalCDORevision newObject : newObjects)
- {
- newObject.adjustForCommit(branch, timeStamp);
- }
- }
-
- protected void lockObjects() throws InterruptedException
- {
- lockedObjects.clear();
- lockedTargets = null;
-
- try
- {
- final boolean supportingBranches = repository.isSupportingBranches();
-
- CDOFeatureDeltaVisitor deltaTargetLocker = null;
- if (ensuringReferentialIntegrity)
- {
- final Set<CDOID> newIDs = new HashSet<CDOID>();
- for (int i = 0; i < newObjects.length; i++)
- {
- InternalCDORevision newRevision = newObjects[i];
- CDOID newID = newRevision.getID();
- if (newID instanceof CDOIDObject)
- {
- // After merges newObjects may contain non-TEMP ids
- newIDs.add(newID);
- }
- }
-
- deltaTargetLocker = new CDOFeatureDeltaVisitorImpl()
- {
- @Override
- public void visit(CDOAddFeatureDelta delta)
- {
- lockTarget(delta.getValue(), newIDs, supportingBranches);
- }
-
- @Override
- public void visit(CDOSetFeatureDelta delta)
- {
- lockTarget(delta.getValue(), newIDs, supportingBranches);
- }
- };
-
- CDOReferenceAdjuster revisionTargetLocker = new CDOReferenceAdjuster()
- {
- public Object adjustReference(Object value, EStructuralFeature feature, int index)
- {
- lockTarget(value, newIDs, supportingBranches);
- return value;
- }
- };
-
- for (int i = 0; i < newObjects.length; i++)
- {
- InternalCDORevision newRevision = newObjects[i];
- newRevision.adjustReferences(revisionTargetLocker);
- }
- }
-
- for (int i = 0; i < dirtyObjectDeltas.length; i++)
- {
- InternalCDORevisionDelta delta = dirtyObjectDeltas[i];
- CDOID id = delta.getID();
- Object key = lockManager.getLockKey(id, transaction.getBranch());
- lockedObjects.add(new DeltaLockWrapper(key, delta));
-
- if (hasContainmentChanges(delta))
- {
- if (isContainerLocked(delta))
- {
- throw new ContainmentCycleDetectedException("Parent (" + key
- + ") is already locked for containment changes");
- }
- }
- }
-
- for (int i = 0; i < dirtyObjectDeltas.length; i++)
- {
- InternalCDORevisionDelta delta = dirtyObjectDeltas[i];
- if (deltaTargetLocker != null)
- {
- delta.accept(deltaTargetLocker);
- }
- }
-
- for (int i = 0; i < detachedObjects.length; i++)
- {
- CDOID id = detachedObjects[i];
- Object key = lockManager.getLockKey(id, transaction.getBranch());
- lockedObjects.add(key);
- }
-
- if (!lockedObjects.isEmpty())
- {
- // First lock all objects (incl. possible ref targets).
- // This is a transient operation, it does not check for existance!
- lockManager.lock2(LockType.WRITE, transaction, lockedObjects, 1000);
-
- // If all locks could be acquired, check if locked targets do still exist
- if (lockedTargets != null)
- {
- for (CDOID id : lockedTargets)
- {
- InternalCDORevision revision = //
- revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true);
-
- if (revision == null || revision instanceof DetachedCDORevision)
- {
- throw new IllegalStateException("Object " + id
- + " can not be referenced anymore because it has been detached");
- }
- }
- }
- }
- }
- catch (RuntimeException ex)
- {
- lockedObjects.clear();
- lockedTargets = null;
- throw ex;
- }
- }
-
- /**
- * Iterates up the eContainers of an object and returns <code>true</code> on the first parent locked by another view.
- *
- * @return <code>true</code> if any parent is locked, <code>false</code> otherwise.
- */
- private boolean isContainerLocked(InternalCDORevisionDelta delta)
- {
- CDOID id = delta.getID();
- InternalCDORevision revision = revisionManager.getRevisionByVersion(id, delta, CDORevision.UNCHUNKED, true);
- if (revision == null)
- {
- // Can happen with non-auditing cache
- throw new ConcurrentModificationException("Attempt by " + transaction + " to modify historical revision: "
- + CDORevisionUtil.copyRevisionKey(delta));
- }
-
- return isContainerLocked(revision);
- }
-
- private boolean isContainerLocked(InternalCDORevision revision)
- {
- CDOID id = (CDOID)revision.getContainerID();
- if (CDOIDUtil.isNull(id))
- {
- return false;
- }
-
- Object key = lockManager.getLockKey(id, transaction.getBranch());
- DeltaLockWrapper lockWrapper = new DeltaLockWrapper(key, null);
-
- if (lockManager.hasLockByOthers(LockType.WRITE, transaction, lockWrapper))
- {
- Object object = lockManager.getLockEntryObject(lockWrapper);
- if (object instanceof DeltaLockWrapper)
- {
- InternalCDORevisionDelta delta = ((DeltaLockWrapper)object).getDelta();
- if (delta != null && hasContainmentChanges(delta))
- {
- return true;
- }
- }
- }
-
- InternalCDORevision parent = revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED,
- CDORevision.DEPTH_NONE, true);
-
- if (parent != null)
- {
- return isContainerLocked(parent);
- }
-
- return false;
- }
-
- private boolean hasContainmentChanges(InternalCDORevisionDelta delta)
- {
- for (CDOFeatureDelta featureDelta : delta.getFeatureDeltas())
- {
- EStructuralFeature feature = featureDelta.getFeature();
- if (feature instanceof EReference)
- {
- if (((EReference)feature).isContainment())
- {
- return true;
- }
- }
- }
-
- return false;
- }
-
- private void lockTarget(Object value, Set<CDOID> newIDs, boolean supportingBranches)
- {
- if (value instanceof CDOIDObject)
- {
- CDOIDObject id = (CDOIDObject)value;
- if (id.isNull())
- {
- return;
- }
-
- if (newIDs.contains(id))
- {
- // After merges newObjects may contain non-TEMP ids
- return;
- }
-
- if (detachedObjectTypes != null && detachedObjectTypes.containsKey(id))
- {
- throw new IllegalStateException("This commit deletes object " + id + " and adds a reference at the same time");
- }
-
- // Let this object be locked
- Object key = lockManager.getLockKey(id, transaction.getBranch());
- lockedObjects.add(key);
-
- // Let this object be checked for existance after it has been locked
- if (lockedTargets == null)
- {
- lockedTargets = new ArrayList<CDOID>();
- }
-
- lockedTargets.add(id);
- }
- }
-
- protected void checkXRefs()
- {
- if (ensuringReferentialIntegrity && detachedObjectTypes != null)
- {
- XRefContext context = new XRefContext();
- xRefs = context.getXRefs(accessor);
- if (!xRefs.isEmpty())
- {
- rollbackMessage = "Referential integrity violated";
- }
- }
- }
-
- private synchronized void unlockObjects()
- {
- if (!lockedObjects.isEmpty())
- {
- lockManager.unlock2(LockType.WRITE, transaction, lockedObjects);
- lockedObjects.clear();
- }
-
- if (detachedObjects.length > 0)
- {
- boolean branching = getTransaction().getRepository().isSupportingBranches();
- Collection<? extends Object> unlockables = null;
- if (branching)
- {
- List<CDOIDAndBranch> keys = new LinkedList<CDOIDAndBranch>();
- for (CDOID id : detachedObjects)
- {
- CDOIDAndBranch idAndBranch = CDOIDUtil.createIDAndBranch(id, transaction.getBranch());
- keys.add(idAndBranch);
- }
-
- unlockables = keys;
- }
- else
- {
- unlockables = Arrays.asList(detachedObjects);
- }
-
- lockManager.unlock2(transaction, unlockables);
- }
- }
-
- private void computeDirtyObjects(OMMonitor monitor)
- {
- try
- {
- monitor.begin(dirtyObjectDeltas.length);
- for (int i = 0; i < dirtyObjectDeltas.length; i++)
- {
- dirtyObjects[i] = computeDirtyObject(dirtyObjectDeltas[i]);
- if (dirtyObjects[i] == null)
- {
- throw new IllegalStateException("Can not retrieve origin revision for " + dirtyObjectDeltas[i]); //$NON-NLS-1$
- }
-
- monitor.worked();
- }
- }
- finally
- {
- monitor.done();
- }
- }
-
- private InternalCDORevision computeDirtyObject(InternalCDORevisionDelta delta)
- {
- CDOBranch branch = transaction.getBranch();
- CDOID id = delta.getID();
-
- InternalCDORevision oldRevision = null;
-
- try
- {
- oldRevision = revisionManager.getRevisionByVersion(id, delta, CDORevision.UNCHUNKED, true);
- if (oldRevision != null)
- {
- if (ObjectUtil.equals(oldRevision.getBranch(), branch) && oldRevision.isHistorical())
- {
- oldRevision = null;
- }
- }
- }
- catch (Exception ex)
- {
- OM.LOG.error(ex);
- oldRevision = null;
- }
-
- if (oldRevision == null)
- {
- throw new ConcurrentModificationException("Attempt by " + transaction + " to modify historical revision: "
- + delta);
- }
-
- // Make sure all chunks are loaded
- for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(oldRevision.getEClass()))
- {
- if (feature.isMany())
- {
- repository.ensureChunk(oldRevision, feature, 0, oldRevision.getList(feature).size());
- }
- }
-
- InternalCDORevision newRevision = oldRevision.copy();
- newRevision.adjustForCommit(branch, timeStamp);
-
- delta.apply(newRevision);
- return newRevision;
- }
-
- private void applyIDMappings(InternalCDORevision[] revisions, OMMonitor monitor)
- {
- try
- {
- monitor.begin(revisions.length);
- for (InternalCDORevision revision : revisions)
- {
- if (revision != null)
- {
- CDOID newID = idMappings.get(revision.getID());
- if (newID != null)
- {
- revision.setID(newID);
- }
-
- revision.adjustReferences(idMapper);
- monitor.worked();
- }
- }
- }
- finally
- {
- monitor.done();
- }
- }
-
- public synchronized void rollback(String message)
- {
- // Check if we already rolled back
- if (rollbackMessage == null)
- {
- rollbackMessage = message;
- unlockObjects();
- if (accessor != null)
- {
- try
- {
- accessor.rollback();
- }
- catch (RuntimeException ex)
- {
- OM.LOG.warn("Problem while rolling back the transaction", ex); //$NON-NLS-1$
- }
- finally
- {
- repository.failCommit(timeStamp);
- }
- }
- }
- }
-
- protected IStoreAccessor getAccessor()
- {
- return accessor;
- }
-
- private void updateInfraStructure(OMMonitor monitor)
- {
- try
- {
- monitor.begin(8);
- addNewPackageUnits(monitor.fork());
- addRevisions(newObjects, monitor.fork());
- addRevisions(dirtyObjects, monitor.fork());
- reviseDetachedObjects(monitor.fork());
-
- unlockObjects();
- monitor.worked();
-
- applyLocksOnNewObjects();
- monitor.worked();
-
- if (isAutoReleaseLocksEnabled())
- {
- postCommitLockStates = repository.getLockingManager().unlock2(true, transaction);
- if (!postCommitLockStates.isEmpty())
- {
- // TODO (CD) Does doing this here make sense?
- // The commit notifications get sent later, from postCommit.
- sendLockNotifications(postCommitLockStates);
- }
- }
-
- monitor.worked();
- repository.notifyWriteAccessHandlers(transaction, this, false, monitor.fork());
- }
- catch (Throwable t)
- {
- handleException(t);
- }
- finally
- {
- monitor.done();
- }
- }
-
- private void applyLocksOnNewObjects() throws InterruptedException
- {
- final CDOLockOwner owner = CDOLockUtil.createLockOwner(transaction);
-
- for (CDOLockState lockState : locksOnNewObjects)
- {
- Object target = lockState.getLockedObject();
-
- if (transaction.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE)
- {
- CDOIDAndBranch idAndBranch = target instanceof CDOIDAndBranch ? (CDOIDAndBranch)target : null;
- CDOID id = idAndBranch != null ? ((CDOIDAndBranch)target).getID() : (CDOID)target;
- CDOID newID = idMappings.get(id);
- CheckUtil.checkNull(newID, "newID");
-
- target = idAndBranch != null ? CDOIDUtil.createIDAndBranch(newID, idAndBranch.getBranch()) : newID;
- }
-
- for (LockType type : LockType.values())
- {
- if (lockState.isLocked(type, owner, false))
- {
- lockManager.lock2(type, transaction, Collections.singleton(target), 0);
- }
- }
- }
- }
-
- private void sendLockNotifications(List<LockState<Object, IView>> newLockStates)
- {
- CDOLockState[] newStates = Repository.toCDOLockStates(newLockStates);
-
- long timeStamp = getTimeStamp();
- InternalTransaction tx = getTransaction();
- CDOBranch branch = tx.getBranch();
- Operation unlock = Operation.UNLOCK;
-
- CDOLockChangeInfo info = CDOLockUtil.createLockChangeInfo(timeStamp, tx, branch, unlock, null, newStates);
- repository.getSessionManager().sendLockNotification(tx.getSession(), info);
- }
-
- private void addNewPackageUnits(OMMonitor monitor)
- {
- InternalCDOPackageRegistry repositoryPackageRegistry = repository.getPackageRegistry(false);
- synchronized (repositoryPackageRegistry)
- {
- try
- {
- monitor.begin(newPackageUnits.length);
- for (int i = 0; i < newPackageUnits.length; i++)
- {
- newPackageUnits[i].setState(CDOPackageUnit.State.LOADED);
- repositoryPackageRegistry.putPackageUnit(newPackageUnits[i]);
- monitor.worked();
- }
- }
- finally
- {
- monitor.done();
- }
- }
- }
-
- private void addRevisions(CDORevision[] revisions, OMMonitor monitor)
- {
- try
- {
- monitor.begin(revisions.length);
- for (CDORevision revision : revisions)
- {
- if (revision != null)
- {
- revisionManager.addRevision(revision);
- }
-
- monitor.worked();
- }
- }
- finally
- {
- monitor.done();
- }
- }
-
- private void reviseDetachedObjects(OMMonitor monitor)
- {
- try
- {
- monitor.begin(cachedDetachedRevisions.length);
- long revised = getBranchPoint().getTimeStamp() - 1;
- for (InternalCDORevision revision : cachedDetachedRevisions)
- {
- if (revision != null)
- {
- revision.setRevised(revised);
- }
-
- monitor.worked();
- }
- }
- finally
- {
- monitor.done();
- }
- }
-
- private void detachObjects(OMMonitor monitor)
- {
- int size = detachedObjects.length;
- cachedDetachedRevisions = new InternalCDORevision[size];
-
- CDOID[] detachedObjects = getDetachedObjects();
-
- try
- {
- monitor.begin(size);
- for (int i = 0; i < size; i++)
- {
- CDOID id = detachedObjects[i];
-
- // Remember the cached revision that must be revised after successful commit through updateInfraStructure
- cachedDetachedRevisions[i] = (InternalCDORevision)revisionManager.getCache().getRevision(id, transaction);
- monitor.worked();
- }
- }
- finally
- {
- monitor.done();
- }
- }
-
- @Override
- public String toString()
- {
- return MessageFormat.format("TransactionCommitContext[{0}, {1}, {2}]", transaction.getSession(), transaction, //$NON-NLS-1$
- CDOCommonUtil.formatTimeStamp(timeStamp));
- }
-
- /**
- * @author Eike Stepper
- */
- public static final class TransactionPackageRegistry extends CDOPackageRegistryImpl
- {
- private static final long serialVersionUID = 1L;
-
- public TransactionPackageRegistry(InternalCDOPackageRegistry repositoryPackageRegistry)
- {
- delegateRegistry = repositoryPackageRegistry;
- setPackageLoader(repositoryPackageRegistry.getPackageLoader());
- }
-
- @Override
- public synchronized void putPackageUnit(InternalCDOPackageUnit packageUnit)
- {
- LifecycleUtil.checkActive(this);
- packageUnit.setPackageRegistry(this);
- for (InternalCDOPackageInfo packageInfo : packageUnit.getPackageInfos())
- {
- EPackage ePackage = packageInfo.getEPackage();
- basicPut(ePackage.getNsURI(), ePackage);
- }
-
- resetInternalCaches();
- }
-
- @Override
- protected void disposePackageUnits()
- {
- // Do nothing
- }
-
- @Override
- public Collection<Object> values()
- {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * @author Martin Fluegge
- */
- private static final class DeltaLockWrapper implements CDOIDAndBranch
- {
- private Object key;
-
- private InternalCDORevisionDelta delta;
-
- public DeltaLockWrapper(Object key, InternalCDORevisionDelta delta)
- {
- this.key = key;
- this.delta = delta;
- }
-
- public Object getKey()
- {
- return key;
- }
-
- public InternalCDORevisionDelta getDelta()
- {
- return delta;
- }
-
- public CDOID getID()
- {
- return key instanceof CDOIDAndBranch ? ((CDOIDAndBranch)key).getID() : (CDOID)key;
- }
-
- public CDOBranch getBranch()
- {
- return key instanceof CDOIDAndBranch ? ((CDOIDAndBranch)key).getBranch() : null;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (obj instanceof DeltaLockWrapper)
- {
- DeltaLockWrapper wrapper = (DeltaLockWrapper)obj;
- return key.equals(wrapper.getKey());
- }
-
- return key.equals(obj);
- }
-
- @Override
- public int hashCode()
- {
- return key.hashCode();
- }
-
- @Override
- public String toString()
- {
- return key.toString();
- }
- }
-
- /**
- * @author Eike Stepper
- */
- private final class XRefContext implements QueryXRefsContext
- {
- private Map<EClass, List<EReference>> sourceCandidates = new HashMap<EClass, List<EReference>>();
-
- private Set<CDOID> detachedIDs = new HashSet<CDOID>();
-
- private Set<CDOID> dirtyIDs = new HashSet<CDOID>();
-
- private List<CDOIDReference> result = new ArrayList<CDOIDReference>();
-
- public XRefContext()
- {
- XRefsQueryHandler.collectSourceCandidates(transaction, detachedObjectTypes.values(), sourceCandidates);
-
- for (CDOID id : detachedObjects)
- {
- detachedIDs.add(id);
- }
-
- for (InternalCDORevision revision : dirtyObjects)
- {
- dirtyIDs.add(revision.getID());
- }
- }
-
- public List<CDOIDReference> getXRefs(IStoreAccessor accessor)
- {
- accessor.queryXRefs(this);
- checkDirtyObjects();
- return result;
- }
-
- private void checkDirtyObjects()
- {
- final CDOID[] dirtyID = { null };
- CDOReferenceAdjuster dirtyObjectChecker = new CDOReferenceAdjuster()
- {
- public Object adjustReference(Object targetID, EStructuralFeature feature, int index)
- {
- if (feature != CDOContainerFeatureDelta.CONTAINER_FEATURE)
- {
- if (detachedIDs.contains(targetID))
- {
- result.add(new CDOIDReference((CDOID)targetID, dirtyID[0], feature, index));
- }
-
- }
-
- return targetID;
- }
- };
-
- for (InternalCDORevision dirtyObject : dirtyObjects)
- {
- dirtyID[0] = dirtyObject.getID();
- dirtyObject.adjustReferences(dirtyObjectChecker);
- }
- }
-
- public long getTimeStamp()
- {
- return CDOBranchPoint.UNSPECIFIED_DATE;
- }
-
- public CDOBranch getBranch()
- {
- return transaction.getBranch();
- }
-
- public Map<CDOID, EClass> getTargetObjects()
- {
- return detachedObjectTypes;
- }
-
- public EReference[] getSourceReferences()
- {
- return new EReference[0];
- }
-
- public Map<EClass, List<EReference>> getSourceCandidates()
- {
- return sourceCandidates;
- }
-
- public int getMaxResults()
- {
- return CDOQueryInfo.UNLIMITED_RESULTS;
- }
-
- public boolean addXRef(CDOID targetID, CDOID sourceID, EReference sourceReference, int sourceIndex)
- {
- if (CDOIDUtil.isNull(targetID))
- {
- // Compensate potential issues with the XRef implementation in the store accessor.
- return true;
- }
-
- if (detachedIDs.contains(sourceID))
- {
- // Ignore XRefs from objects that are about to be detached themselves by this commit.
- return true;
- }
-
- if (dirtyIDs.contains(sourceID))
- {
- // Ignore XRefs from objects that are about to be modified by this commit. They're handled later in getXRefs().
- return true;
- }
-
- result.add(new CDOIDReference(targetID, sourceID, sourceReference, sourceIndex));
- return true;
- }
- }
-}
+/*
+ * Copyright (c) 2004 - 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:
+ * Simon McDuff - initial API and implementation
+ * Eike Stepper - maintenance
+ * Martin Fluegge - maintenance, bug 318518
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository.IDGenerationLocation;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOCommitData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDObject;
+import org.eclipse.emf.cdo.common.id.CDOIDReference;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.security.NoPermissionException;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.internal.common.commit.CDOCommitDataImpl;
+import org.eclipse.emf.cdo.internal.common.commit.FailureCommitInfo;
+import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl;
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.ContainmentCycleDetectedException;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.CDOFeatureDeltaVisitorImpl;
+import org.eclipse.emf.cdo.spi.common.revision.CDOIDMapper;
+import org.eclipse.emf.cdo.spi.common.revision.CDOReferenceAdjuster;
+import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.common.revision.StubCDORevision;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+
+import org.eclipse.net4j.util.CheckUtil;
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.collection.IndexedList;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
+import org.eclipse.net4j.util.io.ExtendedDataInputStream;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.monitor.Monitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author Simon McDuff
+ * @since 2.0
+ */
+public class TransactionCommitContext implements InternalCommitContext
+{
+ private static final InternalCDORevision DETACHED = new StubCDORevision(null);
+
+ private final InternalTransaction transaction;
+
+ private InternalRepository repository;
+
+ private InternalCDORevisionManager revisionManager;
+
+ private InternalLockManager lockManager;
+
+ private InternalCDOPackageRegistry repositoryPackageRegistry;
+
+ private boolean packageRegistryLocked;
+
+ private TransactionPackageRegistry packageRegistry;
+
+ private IStoreAccessor accessor;
+
+ private long timeStamp = CDORevision.UNSPECIFIED_DATE;
+
+ private long previousTimeStamp = CDORevision.UNSPECIFIED_DATE;
+
+ private String commitComment;
+
+ private InternalCDOPackageUnit[] newPackageUnits = new InternalCDOPackageUnit[0];
+
+ private CDOLockState[] locksOnNewObjects = new CDOLockState[0];
+
+ private InternalCDORevision[] newObjects = new InternalCDORevision[0];
+
+ private InternalCDORevisionDelta[] dirtyObjectDeltas = new InternalCDORevisionDelta[0];
+
+ private CDOID[] detachedObjects = new CDOID[0];
+
+ private Map<CDOID, EClass> detachedObjectTypes;
+
+ private InternalCDORevision[] dirtyObjects = new InternalCDORevision[0];
+
+ private InternalCDORevision[] cachedDetachedRevisions = new InternalCDORevision[0];
+
+ private Map<CDOID, InternalCDORevision> cachedRevisions;
+
+ private Set<Object> lockedObjects = new HashSet<Object>();
+
+ private List<CDOID> lockedTargets;
+
+ private ConcurrentMap<CDOID, CDOID> idMappings = new ConcurrentHashMap<CDOID, CDOID>();
+
+ private CDOReferenceAdjuster idMapper = new CDOIDMapper(idMappings);
+
+ private String rollbackMessage;
+
+ private List<CDOIDReference> xRefs;
+
+ private List<LockState<Object, IView>> postCommitLockStates;
+
+ private boolean ensuringReferentialIntegrity;
+
+ private boolean autoReleaseLocksEnabled;
+
+ private ExtendedDataInputStream lobs;
+
+ public TransactionCommitContext(InternalTransaction transaction)
+ {
+ this.transaction = transaction;
+
+ repository = transaction.getRepository();
+ revisionManager = repository.getRevisionManager();
+ lockManager = repository.getLockingManager();
+ ensuringReferentialIntegrity = repository.isEnsuringReferentialIntegrity();
+
+ repositoryPackageRegistry = repository.getPackageRegistry(false);
+ packageRegistry = new TransactionPackageRegistry(repositoryPackageRegistry);
+ packageRegistry.activate();
+ }
+
+ public InternalTransaction getTransaction()
+ {
+ return transaction;
+ }
+
+ public CDOBranchPoint getBranchPoint()
+ {
+ return transaction.getBranch().getPoint(timeStamp);
+ }
+
+ public String getUserID()
+ {
+ return transaction.getSession().getUserID();
+ }
+
+ public String getCommitComment()
+ {
+ return commitComment;
+ }
+
+ public boolean isAutoReleaseLocksEnabled()
+ {
+ return autoReleaseLocksEnabled;
+ }
+
+ public String getRollbackMessage()
+ {
+ return rollbackMessage;
+ }
+
+ public List<CDOIDReference> getXRefs()
+ {
+ return xRefs;
+ }
+
+ public InternalCDOPackageRegistry getPackageRegistry()
+ {
+ return packageRegistry;
+ }
+
+ public InternalCDOPackageUnit[] getNewPackageUnits()
+ {
+ return newPackageUnits;
+ }
+
+ public CDOLockState[] getLocksOnNewObjects()
+ {
+ return locksOnNewObjects;
+ }
+
+ public InternalCDORevision[] getNewObjects()
+ {
+ return newObjects;
+ }
+
+ public InternalCDORevision[] getDirtyObjects()
+ {
+ return dirtyObjects;
+ }
+
+ public CDOID[] getDetachedObjects()
+ {
+ return detachedObjects;
+ }
+
+ public Map<CDOID, EClass> getDetachedObjectTypes()
+ {
+ return detachedObjectTypes;
+ }
+
+ public InternalCDORevision[] getDetachedRevisions()
+ {
+ // This array can contain null values as they only come from the cache!
+ for (InternalCDORevision cachedDetachedRevision : cachedDetachedRevisions)
+ {
+ if (cachedDetachedRevision == null)
+ {
+ throw new AssertionError("Detached revisions are incomplete");
+ }
+ }
+
+ return cachedDetachedRevisions;
+ }
+
+ public InternalCDORevisionDelta[] getDirtyObjectDeltas()
+ {
+ return dirtyObjectDeltas;
+ }
+
+ public CDORevision getRevision(CDOID id)
+ {
+ if (cachedRevisions == null)
+ {
+ cachedRevisions = cacheRevisions();
+ }
+
+ // Try "after state"
+ InternalCDORevision revision = cachedRevisions.get(id);
+ if (revision == DETACHED)
+ {
+ return null;
+ }
+
+ if (revision != null)
+ {
+ return revision;
+ }
+
+ // Fall back to "before state"
+ return transaction.getRevision(id);
+ }
+
+ private Map<CDOID, InternalCDORevision> cacheRevisions()
+ {
+ Map<CDOID, InternalCDORevision> cache = new HashMap<CDOID, InternalCDORevision>();
+ if (newObjects != null)
+ {
+ for (int i = 0; i < newObjects.length; i++)
+ {
+ InternalCDORevision revision = newObjects[i];
+ cache.put(revision.getID(), revision);
+ }
+ }
+
+ if (dirtyObjects != null)
+ {
+ for (int i = 0; i < dirtyObjects.length; i++)
+ {
+ InternalCDORevision revision = dirtyObjects[i];
+ cache.put(revision.getID(), revision);
+ }
+ }
+
+ if (detachedObjects != null)
+ {
+ for (int i = 0; i < detachedObjects.length; i++)
+ {
+ cache.put(detachedObjects[i], DETACHED);
+ }
+ }
+
+ return cache;
+ }
+
+ public Map<CDOID, CDOID> getIDMappings()
+ {
+ return Collections.unmodifiableMap(idMappings);
+ }
+
+ public void addIDMapping(CDOID oldID, CDOID newID)
+ {
+ if (CDOIDUtil.isNull(newID) || newID.isTemporary())
+ {
+ throw new IllegalStateException("newID=" + newID); //$NON-NLS-1$
+ }
+
+ CDOID previousMapping = idMappings.putIfAbsent(oldID, newID);
+ if (previousMapping != null)
+ {
+ throw new IllegalStateException("previousMapping != null"); //$NON-NLS-1$
+ }
+ }
+
+ public void applyIDMappings(OMMonitor monitor)
+ {
+ boolean mapIDs = !idMappings.isEmpty();
+ monitor.begin(1 + (mapIDs ? newObjects.length + dirtyObjects.length + dirtyObjectDeltas.length : 0));
+
+ try
+ {
+ if (mapIDs)
+ {
+ applyIDMappings(newObjects, monitor.fork(newObjects.length));
+ applyIDMappings(dirtyObjects, monitor.fork(dirtyObjects.length));
+ for (CDORevisionDelta dirtyObjectDelta : dirtyObjectDeltas)
+ {
+ ((InternalCDORevisionDelta)dirtyObjectDelta).adjustReferences(idMapper);
+ monitor.worked();
+ }
+ }
+
+ // Do not notify handlers before the IDs are fully mapped!
+ notifyBeforeCommitting(monitor);
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ protected void notifyBeforeCommitting(OMMonitor monitor)
+ {
+ repository.notifyWriteAccessHandlers(transaction, this, true, monitor.fork());
+ }
+
+ public void preWrite()
+ {
+ // Allocate a store writer
+ accessor = repository.getStore().getWriter(transaction);
+
+ // Make the store writer available in a ThreadLocal variable
+ StoreThreadLocal.setAccessor(accessor);
+ StoreThreadLocal.setCommitContext(this);
+ }
+
+ public void setNewPackageUnits(InternalCDOPackageUnit[] newPackageUnits)
+ {
+ this.newPackageUnits = newPackageUnits;
+ }
+
+ public void setLocksOnNewObjects(CDOLockState[] locksOnNewObjects)
+ {
+ this.locksOnNewObjects = locksOnNewObjects;
+ }
+
+ public void setNewObjects(InternalCDORevision[] newObjects)
+ {
+ this.newObjects = newObjects;
+ }
+
+ public void setDirtyObjectDeltas(InternalCDORevisionDelta[] dirtyObjectDeltas)
+ {
+ this.dirtyObjectDeltas = dirtyObjectDeltas;
+ }
+
+ public void setDetachedObjects(CDOID[] detachedObjects)
+ {
+ this.detachedObjects = detachedObjects;
+ }
+
+ public void setDetachedObjectTypes(Map<CDOID, EClass> detachedObjectTypes)
+ {
+ this.detachedObjectTypes = detachedObjectTypes;
+ }
+
+ public void setAutoReleaseLocksEnabled(boolean on)
+ {
+ autoReleaseLocksEnabled = on;
+ }
+
+ public void setCommitComment(String commitComment)
+ {
+ this.commitComment = commitComment;
+ }
+
+ public ExtendedDataInputStream getLobs()
+ {
+ return lobs;
+ }
+
+ public void setLobs(ExtendedDataInputStream in)
+ {
+ lobs = in;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void write(OMMonitor monitor)
+ {
+ try
+ {
+ monitor.begin(107);
+ dirtyObjects = new InternalCDORevision[dirtyObjectDeltas.length];
+
+ if (newPackageUnits.length != 0)
+ {
+ repository.getPackageRegistryCommitLock().acquire();
+ packageRegistryLocked = true;
+
+ List<InternalCDOPackageUnit> noDuplicates = new ArrayList<InternalCDOPackageUnit>();
+ for (InternalCDOPackageUnit newPackageUnit : newPackageUnits)
+ {
+ String id = newPackageUnit.getID();
+ if (!repositoryPackageRegistry.containsKey(id))
+ {
+ noDuplicates.add(newPackageUnit);
+ }
+ }
+
+ int newSize = noDuplicates.size();
+ if (newPackageUnits.length != newSize)
+ {
+ newPackageUnits = noDuplicates.toArray(new InternalCDOPackageUnit[newSize]);
+ }
+ }
+
+ lockObjects(); // Can take long and must come before setTimeStamp()
+ monitor.worked();
+
+ setTimeStamp(monitor.fork());
+
+ adjustForCommit();
+ monitor.worked();
+
+ computeDirtyObjects(monitor.fork());
+
+ checkXRefs();
+ monitor.worked();
+
+ if (rollbackMessage == null)
+ {
+ detachObjects(monitor.fork());
+ accessor.write(this, monitor.fork(100));
+ }
+ }
+ catch (Throwable t)
+ {
+ handleException(t);
+ }
+ finally
+ {
+ finishMonitor(monitor);
+ }
+ }
+
+ public void commit(OMMonitor monitor)
+ {
+ try
+ {
+ monitor.begin(101);
+ accessor.commit(monitor.fork(100));
+ updateInfraStructure(monitor.fork());
+
+ // Bugzilla 297940
+ repository.endCommit(timeStamp);
+ }
+ catch (Throwable ex)
+ {
+ handleException(ex);
+ }
+ finally
+ {
+ finishMonitor(monitor);
+ }
+ }
+
+ public List<LockState<Object, IView>> getPostCommmitLockStates()
+ {
+ return postCommitLockStates;
+ }
+
+ private void handleException(Throwable ex)
+ {
+ try
+ {
+ OM.LOG.error(ex);
+ String storeClass = repository.getStore().getClass().getSimpleName();
+ rollback("Rollback in " + storeClass + ": " + StringUtil.formatException(ex)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ catch (Exception ex1)
+ {
+ if (rollbackMessage == null)
+ {
+ rollbackMessage = ex1.getMessage();
+ }
+
+ try
+ {
+ OM.LOG.error(ex1);
+ }
+ catch (Exception ignore)
+ {
+ }
+ }
+ }
+
+ private void finishMonitor(OMMonitor monitor)
+ {
+ try
+ {
+ monitor.done();
+ }
+ catch (Exception ex)
+ {
+ try
+ {
+ OM.LOG.warn(ex);
+ }
+ catch (Exception ignore)
+ {
+ }
+ }
+ }
+
+ private void setTimeStamp(OMMonitor mmonitor)
+ {
+ long[] times = createTimeStamp(mmonitor); // Could throw an exception
+ timeStamp = times[0];
+ previousTimeStamp = times[1];
+ CheckUtil.checkState(timeStamp != CDOBranchPoint.UNSPECIFIED_DATE, "Commit timestamp must not be 0");
+ }
+
+ protected long[] createTimeStamp(OMMonitor monitor)
+ {
+ return repository.createCommitTimeStamp(monitor);
+ }
+
+ protected long getTimeStamp()
+ {
+ return timeStamp;
+ }
+
+ protected void setTimeStamp(long timeStamp)
+ {
+ repository.forceCommitTimeStamp(timeStamp, new Monitor());
+ this.timeStamp = timeStamp;
+ }
+
+ public long getPreviousTimeStamp()
+ {
+ return previousTimeStamp;
+ }
+
+ public void postCommit(boolean success)
+ {
+ if (packageRegistryLocked)
+ {
+ repository.getPackageRegistryCommitLock().release();
+ }
+
+ try
+ {
+ InternalSession sender = transaction.getSession();
+ CDOCommitInfo commitInfo = success ? createCommitInfo() : createFailureCommitInfo();
+
+ repository.sendCommitNotification(sender, commitInfo);
+ }
+ catch (Exception ex)
+ {
+ OM.LOG.warn("A problem occured while notifying other sessions", ex);
+ }
+ finally
+ {
+ StoreThreadLocal.release();
+ accessor = null;
+ lockedTargets = null;
+
+ if (packageRegistry != null)
+ {
+ packageRegistry.deactivate();
+ packageRegistry = null;
+ }
+ }
+ }
+
+ public CDOCommitInfo createCommitInfo()
+ {
+ CDOBranch branch = transaction.getBranch();
+ String userID = transaction.getSession().getUserID();
+ CDOCommitData commitData = createCommitData();
+
+ InternalCDOCommitInfoManager commitInfoManager = repository.getCommitInfoManager();
+ return commitInfoManager.createCommitInfo(branch, timeStamp, previousTimeStamp, userID, commitComment, commitData);
+ }
+
+ public CDOCommitInfo createFailureCommitInfo()
+ {
+ return new FailureCommitInfo(timeStamp, previousTimeStamp);
+ }
+
+ private CDOCommitData createCommitData()
+ {
+ List<CDOPackageUnit> newPackageUnitsCollection = new IndexedList.ArrayBacked<CDOPackageUnit>()
+ {
+ @Override
+ protected CDOPackageUnit[] getArray()
+ {
+ return newPackageUnits;
+ }
+ };
+
+ List<CDOIDAndVersion> newObjectsCollection = new IndexedList.ArrayBacked<CDOIDAndVersion>()
+ {
+ @Override
+ protected CDOIDAndVersion[] getArray()
+ {
+ return newObjects;
+ }
+ };
+
+ List<CDORevisionKey> changedObjectsCollection = new IndexedList.ArrayBacked<CDORevisionKey>()
+ {
+ @Override
+ protected CDORevisionKey[] getArray()
+ {
+ return dirtyObjectDeltas;
+ }
+ };
+
+ List<CDOIDAndVersion> detachedObjectsCollection = new IndexedList<CDOIDAndVersion>()
+ {
+ @Override
+ public CDOIDAndVersion get(int i)
+ {
+ if (cachedDetachedRevisions[i] != null)
+ {
+ return cachedDetachedRevisions[i];
+ }
+
+ return CDOIDUtil.createIDAndVersion(detachedObjects[i], CDORevision.UNSPECIFIED_VERSION);
+ }
+
+ @Override
+ public int size()
+ {
+ return detachedObjects.length;
+ }
+ };
+
+ return new CDOCommitDataImpl(newPackageUnitsCollection, newObjectsCollection, changedObjectsCollection,
+ detachedObjectsCollection);
+ }
+
+ protected void adjustForCommit()
+ {
+ for (InternalCDOPackageUnit newPackageUnit : newPackageUnits)
+ {
+ newPackageUnit.setTimeStamp(timeStamp);
+ }
+
+ CDOBranch branch = transaction.getBranch();
+ for (InternalCDORevision newObject : newObjects)
+ {
+ newObject.adjustForCommit(branch, timeStamp);
+ }
+ }
+
+ protected void lockObjects() throws InterruptedException
+ {
+ lockedObjects.clear();
+ lockedTargets = null;
+
+ try
+ {
+ final boolean supportingBranches = repository.isSupportingBranches();
+
+ CDOFeatureDeltaVisitor deltaTargetLocker = null;
+ if (ensuringReferentialIntegrity)
+ {
+ final Set<CDOID> newIDs = new HashSet<CDOID>();
+ for (int i = 0; i < newObjects.length; i++)
+ {
+ InternalCDORevision newRevision = newObjects[i];
+ CDOID newID = newRevision.getID();
+ if (newID instanceof CDOIDObject)
+ {
+ // After merges newObjects may contain non-TEMP ids
+ newIDs.add(newID);
+ }
+ }
+
+ deltaTargetLocker = new CDOFeatureDeltaVisitorImpl()
+ {
+ @Override
+ public void visit(CDOAddFeatureDelta delta)
+ {
+ lockTarget(delta.getValue(), newIDs, supportingBranches);
+ }
+
+ @Override
+ public void visit(CDOSetFeatureDelta delta)
+ {
+ lockTarget(delta.getValue(), newIDs, supportingBranches);
+ }
+ };
+
+ CDOReferenceAdjuster revisionTargetLocker = new CDOReferenceAdjuster()
+ {
+ public Object adjustReference(Object value, EStructuralFeature feature, int index)
+ {
+ lockTarget(value, newIDs, supportingBranches);
+ return value;
+ }
+ };
+
+ for (int i = 0; i < newObjects.length; i++)
+ {
+ InternalCDORevision newRevision = newObjects[i];
+ newRevision.adjustReferences(revisionTargetLocker);
+ }
+ }
+
+ for (int i = 0; i < dirtyObjectDeltas.length; i++)
+ {
+ InternalCDORevisionDelta delta = dirtyObjectDeltas[i];
+ CDOID id = delta.getID();
+ Object key = lockManager.getLockKey(id, transaction.getBranch());
+ lockedObjects.add(new DeltaLockWrapper(key, delta));
+
+ if (hasContainmentChanges(delta))
+ {
+ if (isContainerLocked(delta))
+ {
+ throw new ContainmentCycleDetectedException("Parent (" + key
+ + ") is already locked for containment changes");
+ }
+ }
+ }
+
+ for (int i = 0; i < dirtyObjectDeltas.length; i++)
+ {
+ InternalCDORevisionDelta delta = dirtyObjectDeltas[i];
+ if (deltaTargetLocker != null)
+ {
+ delta.accept(deltaTargetLocker);
+ }
+ }
+
+ for (int i = 0; i < detachedObjects.length; i++)
+ {
+ CDOID id = detachedObjects[i];
+ Object key = lockManager.getLockKey(id, transaction.getBranch());
+ lockedObjects.add(key);
+ }
+
+ if (!lockedObjects.isEmpty())
+ {
+ // First lock all objects (incl. possible ref targets).
+ // This is a transient operation, it does not check for existance!
+ lockManager.lock2(LockType.WRITE, transaction, lockedObjects, 1000);
+
+ // If all locks could be acquired, check if locked targets do still exist
+ if (lockedTargets != null)
+ {
+ for (CDOID id : lockedTargets)
+ {
+ InternalCDORevision revision = //
+ revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true);
+
+ if (revision == null || revision instanceof DetachedCDORevision)
+ {
+ throw new IllegalStateException("Object " + id
+ + " can not be referenced anymore because it has been detached");
+ }
+ }
+ }
+ }
+ }
+ catch (RuntimeException ex)
+ {
+ lockedObjects.clear();
+ lockedTargets = null;
+ throw ex;
+ }
+ }
+
+ /**
+ * Iterates up the eContainers of an object and returns <code>true</code> on the first parent locked by another view.
+ *
+ * @return <code>true</code> if any parent is locked, <code>false</code> otherwise.
+ */
+ private boolean isContainerLocked(InternalCDORevisionDelta delta)
+ {
+ CDOID id = delta.getID();
+ InternalCDORevision revision = revisionManager.getRevisionByVersion(id, delta, CDORevision.UNCHUNKED, true);
+ if (revision == null)
+ {
+ // Can happen with non-auditing cache
+ throw new ConcurrentModificationException("Attempt by " + transaction + " to modify historical revision: "
+ + CDORevisionUtil.copyRevisionKey(delta));
+ }
+
+ return isContainerLocked(revision);
+ }
+
+ private boolean isContainerLocked(InternalCDORevision revision)
+ {
+ CDOID id = (CDOID)revision.getContainerID();
+ if (CDOIDUtil.isNull(id))
+ {
+ return false;
+ }
+
+ Object key = lockManager.getLockKey(id, transaction.getBranch());
+ DeltaLockWrapper lockWrapper = new DeltaLockWrapper(key, null);
+
+ if (lockManager.hasLockByOthers(LockType.WRITE, transaction, lockWrapper))
+ {
+ Object object = lockManager.getLockEntryObject(lockWrapper);
+ if (object instanceof DeltaLockWrapper)
+ {
+ InternalCDORevisionDelta delta = ((DeltaLockWrapper)object).getDelta();
+ if (delta != null && hasContainmentChanges(delta))
+ {
+ return true;
+ }
+ }
+ }
+
+ InternalCDORevision parent = revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED,
+ CDORevision.DEPTH_NONE, true);
+
+ if (parent != null)
+ {
+ return isContainerLocked(parent);
+ }
+
+ return false;
+ }
+
+ private boolean hasContainmentChanges(InternalCDORevisionDelta delta)
+ {
+ for (CDOFeatureDelta featureDelta : delta.getFeatureDeltas())
+ {
+ EStructuralFeature feature = featureDelta.getFeature();
+ if (feature instanceof EReference)
+ {
+ if (((EReference)feature).isContainment())
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private void lockTarget(Object value, Set<CDOID> newIDs, boolean supportingBranches)
+ {
+ if (value instanceof CDOIDObject)
+ {
+ CDOIDObject id = (CDOIDObject)value;
+ if (id.isNull())
+ {
+ return;
+ }
+
+ if (newIDs.contains(id))
+ {
+ // After merges newObjects may contain non-TEMP ids
+ return;
+ }
+
+ if (detachedObjectTypes != null && detachedObjectTypes.containsKey(id))
+ {
+ throw new IllegalStateException("This commit deletes object " + id + " and adds a reference at the same time");
+ }
+
+ // Let this object be locked
+ Object key = lockManager.getLockKey(id, transaction.getBranch());
+ lockedObjects.add(key);
+
+ // Let this object be checked for existance after it has been locked
+ if (lockedTargets == null)
+ {
+ lockedTargets = new ArrayList<CDOID>();
+ }
+
+ lockedTargets.add(id);
+ }
+ }
+
+ protected void checkXRefs()
+ {
+ if (ensuringReferentialIntegrity && detachedObjectTypes != null)
+ {
+ XRefContext context = new XRefContext();
+ xRefs = context.getXRefs(accessor);
+ if (!xRefs.isEmpty())
+ {
+ rollbackMessage = "Referential integrity violated";
+ }
+ }
+ }
+
+ private synchronized void unlockObjects()
+ {
+ if (!lockedObjects.isEmpty())
+ {
+ lockManager.unlock2(LockType.WRITE, transaction, lockedObjects);
+ lockedObjects.clear();
+ }
+
+ if (detachedObjects.length > 0)
+ {
+ boolean branching = getTransaction().getRepository().isSupportingBranches();
+ Collection<? extends Object> unlockables = null;
+ if (branching)
+ {
+ List<CDOIDAndBranch> keys = new LinkedList<CDOIDAndBranch>();
+ for (CDOID id : detachedObjects)
+ {
+ CDOIDAndBranch idAndBranch = CDOIDUtil.createIDAndBranch(id, transaction.getBranch());
+ keys.add(idAndBranch);
+ }
+
+ unlockables = keys;
+ }
+ else
+ {
+ unlockables = Arrays.asList(detachedObjects);
+ }
+
+ lockManager.unlock2(transaction, unlockables);
+ }
+ }
+
+ private void computeDirtyObjects(OMMonitor monitor)
+ {
+ try
+ {
+ monitor.begin(dirtyObjectDeltas.length);
+ for (int i = 0; i < dirtyObjectDeltas.length; i++)
+ {
+ dirtyObjects[i] = computeDirtyObject(dirtyObjectDeltas[i]);
+ if (dirtyObjects[i] == null)
+ {
+ throw new IllegalStateException("Can not retrieve origin revision for " + dirtyObjectDeltas[i]); //$NON-NLS-1$
+ }
+
+ if (!dirtyObjects[i].isWritable())
+ {
+ throw new NoPermissionException(dirtyObjects[i]);
+ }
+
+ monitor.worked();
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ private InternalCDORevision computeDirtyObject(InternalCDORevisionDelta delta)
+ {
+ CDOBranch branch = transaction.getBranch();
+ CDOID id = delta.getID();
+
+ InternalCDORevision oldRevision = null;
+
+ try
+ {
+ oldRevision = revisionManager.getRevisionByVersion(id, delta, CDORevision.UNCHUNKED, true);
+ if (oldRevision != null)
+ {
+ if (ObjectUtil.equals(oldRevision.getBranch(), branch) && oldRevision.isHistorical())
+ {
+ oldRevision = null;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ OM.LOG.error(ex);
+ oldRevision = null;
+ }
+
+ if (oldRevision == null)
+ {
+ throw new ConcurrentModificationException("Attempt by " + transaction + " to modify historical revision: "
+ + delta);
+ }
+
+ // Make sure all chunks are loaded
+ for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(oldRevision.getEClass()))
+ {
+ if (feature.isMany())
+ {
+ repository.ensureChunk(oldRevision, feature, 0, oldRevision.getList(feature).size());
+ }
+ }
+
+ InternalCDORevision newRevision = oldRevision.copy();
+ newRevision.adjustForCommit(branch, timeStamp);
+
+ delta.apply(newRevision);
+ return newRevision;
+ }
+
+ private void applyIDMappings(InternalCDORevision[] revisions, OMMonitor monitor)
+ {
+ try
+ {
+ monitor.begin(revisions.length);
+ for (InternalCDORevision revision : revisions)
+ {
+ if (revision != null)
+ {
+ CDOID newID = idMappings.get(revision.getID());
+ if (newID != null)
+ {
+ revision.setID(newID);
+ }
+
+ revision.adjustReferences(idMapper);
+ monitor.worked();
+ }
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ public synchronized void rollback(String message)
+ {
+ // Check if we already rolled back
+ if (rollbackMessage == null)
+ {
+ rollbackMessage = message;
+ unlockObjects();
+ if (accessor != null)
+ {
+ try
+ {
+ accessor.rollback();
+ }
+ catch (RuntimeException ex)
+ {
+ OM.LOG.warn("Problem while rolling back the transaction", ex); //$NON-NLS-1$
+ }
+ finally
+ {
+ repository.failCommit(timeStamp);
+ }
+ }
+ }
+ }
+
+ protected IStoreAccessor getAccessor()
+ {
+ return accessor;
+ }
+
+ private void updateInfraStructure(OMMonitor monitor)
+ {
+ try
+ {
+ monitor.begin(8);
+ addNewPackageUnits(monitor.fork());
+ addRevisions(newObjects, monitor.fork());
+ addRevisions(dirtyObjects, monitor.fork());
+ reviseDetachedObjects(monitor.fork());
+
+ unlockObjects();
+ monitor.worked();
+
+ applyLocksOnNewObjects();
+ monitor.worked();
+
+ if (isAutoReleaseLocksEnabled())
+ {
+ postCommitLockStates = repository.getLockingManager().unlock2(true, transaction);
+ if (!postCommitLockStates.isEmpty())
+ {
+ // TODO (CD) Does doing this here make sense?
+ // The commit notifications get sent later, from postCommit.
+ sendLockNotifications(postCommitLockStates);
+ }
+ }
+
+ monitor.worked();
+ repository.notifyWriteAccessHandlers(transaction, this, false, monitor.fork());
+ }
+ catch (Throwable t)
+ {
+ handleException(t);
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ private void applyLocksOnNewObjects() throws InterruptedException
+ {
+ final CDOLockOwner owner = CDOLockUtil.createLockOwner(transaction);
+
+ for (CDOLockState lockState : locksOnNewObjects)
+ {
+ Object target = lockState.getLockedObject();
+
+ if (transaction.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE)
+ {
+ CDOIDAndBranch idAndBranch = target instanceof CDOIDAndBranch ? (CDOIDAndBranch)target : null;
+ CDOID id = idAndBranch != null ? ((CDOIDAndBranch)target).getID() : (CDOID)target;
+ CDOID newID = idMappings.get(id);
+ CheckUtil.checkNull(newID, "newID");
+
+ target = idAndBranch != null ? CDOIDUtil.createIDAndBranch(newID, idAndBranch.getBranch()) : newID;
+ }
+
+ for (LockType type : LockType.values())
+ {
+ if (lockState.isLocked(type, owner, false))
+ {
+ lockManager.lock2(type, transaction, Collections.singleton(target), 0);
+ }
+ }
+ }
+ }
+
+ private void sendLockNotifications(List<LockState<Object, IView>> newLockStates)
+ {
+ CDOLockState[] newStates = Repository.toCDOLockStates(newLockStates);
+
+ long timeStamp = getTimeStamp();
+ InternalTransaction tx = getTransaction();
+ CDOBranch branch = tx.getBranch();
+ Operation unlock = Operation.UNLOCK;
+
+ CDOLockChangeInfo info = CDOLockUtil.createLockChangeInfo(timeStamp, tx, branch, unlock, null, newStates);
+ repository.getSessionManager().sendLockNotification(tx.getSession(), info);
+ }
+
+ private void addNewPackageUnits(OMMonitor monitor)
+ {
+ InternalCDOPackageRegistry repositoryPackageRegistry = repository.getPackageRegistry(false);
+ synchronized (repositoryPackageRegistry)
+ {
+ try
+ {
+ monitor.begin(newPackageUnits.length);
+ for (int i = 0; i < newPackageUnits.length; i++)
+ {
+ newPackageUnits[i].setState(CDOPackageUnit.State.LOADED);
+ repositoryPackageRegistry.putPackageUnit(newPackageUnits[i]);
+ monitor.worked();
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+ }
+
+ private void addRevisions(CDORevision[] revisions, OMMonitor monitor)
+ {
+ try
+ {
+ monitor.begin(revisions.length);
+ for (CDORevision revision : revisions)
+ {
+ if (revision != null)
+ {
+ revisionManager.addRevision(revision);
+ }
+
+ monitor.worked();
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ private void reviseDetachedObjects(OMMonitor monitor)
+ {
+ try
+ {
+ monitor.begin(cachedDetachedRevisions.length);
+ long revised = getBranchPoint().getTimeStamp() - 1;
+ for (InternalCDORevision revision : cachedDetachedRevisions)
+ {
+ if (revision != null)
+ {
+ revision.setRevised(revised);
+ }
+
+ monitor.worked();
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ private void detachObjects(OMMonitor monitor)
+ {
+ int size = detachedObjects.length;
+ cachedDetachedRevisions = new InternalCDORevision[size];
+
+ CDOID[] detachedObjects = getDetachedObjects();
+
+ try
+ {
+ monitor.begin(size);
+ for (int i = 0; i < size; i++)
+ {
+ CDOID id = detachedObjects[i];
+
+ // Remember the cached revision that must be revised after successful commit through updateInfraStructure
+ cachedDetachedRevisions[i] = (InternalCDORevision)revisionManager.getCache().getRevision(id, transaction);
+ monitor.worked();
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return MessageFormat.format("TransactionCommitContext[{0}, {1}, {2}]", transaction.getSession(), transaction, //$NON-NLS-1$
+ CDOCommonUtil.formatTimeStamp(timeStamp));
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class TransactionPackageRegistry extends CDOPackageRegistryImpl
+ {
+ private static final long serialVersionUID = 1L;
+
+ public TransactionPackageRegistry(InternalCDOPackageRegistry repositoryPackageRegistry)
+ {
+ delegateRegistry = repositoryPackageRegistry;
+ setPackageLoader(repositoryPackageRegistry.getPackageLoader());
+ }
+
+ @Override
+ public synchronized void putPackageUnit(InternalCDOPackageUnit packageUnit)
+ {
+ LifecycleUtil.checkActive(this);
+ packageUnit.setPackageRegistry(this);
+ for (InternalCDOPackageInfo packageInfo : packageUnit.getPackageInfos())
+ {
+ EPackage ePackage = packageInfo.getEPackage();
+ basicPut(ePackage.getNsURI(), ePackage);
+ }
+
+ resetInternalCaches();
+ }
+
+ @Override
+ protected void disposePackageUnits()
+ {
+ // Do nothing
+ }
+
+ @Override
+ public Collection<Object> values()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * @author Martin Fluegge
+ */
+ private static final class DeltaLockWrapper implements CDOIDAndBranch
+ {
+ private Object key;
+
+ private InternalCDORevisionDelta delta;
+
+ public DeltaLockWrapper(Object key, InternalCDORevisionDelta delta)
+ {
+ this.key = key;
+ this.delta = delta;
+ }
+
+ public Object getKey()
+ {
+ return key;
+ }
+
+ public InternalCDORevisionDelta getDelta()
+ {
+ return delta;
+ }
+
+ public CDOID getID()
+ {
+ return key instanceof CDOIDAndBranch ? ((CDOIDAndBranch)key).getID() : (CDOID)key;
+ }
+
+ public CDOBranch getBranch()
+ {
+ return key instanceof CDOIDAndBranch ? ((CDOIDAndBranch)key).getBranch() : null;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof DeltaLockWrapper)
+ {
+ DeltaLockWrapper wrapper = (DeltaLockWrapper)obj;
+ return key.equals(wrapper.getKey());
+ }
+
+ return key.equals(obj);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return key.hashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ return key.toString();
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private final class XRefContext implements QueryXRefsContext
+ {
+ private Map<EClass, List<EReference>> sourceCandidates = new HashMap<EClass, List<EReference>>();
+
+ private Set<CDOID> detachedIDs = new HashSet<CDOID>();
+
+ private Set<CDOID> dirtyIDs = new HashSet<CDOID>();
+
+ private List<CDOIDReference> result = new ArrayList<CDOIDReference>();
+
+ public XRefContext()
+ {
+ XRefsQueryHandler.collectSourceCandidates(transaction, detachedObjectTypes.values(), sourceCandidates);
+
+ for (CDOID id : detachedObjects)
+ {
+ detachedIDs.add(id);
+ }
+
+ for (InternalCDORevision revision : dirtyObjects)
+ {
+ dirtyIDs.add(revision.getID());
+ }
+ }
+
+ public List<CDOIDReference> getXRefs(IStoreAccessor accessor)
+ {
+ accessor.queryXRefs(this);
+ checkDirtyObjects();
+ return result;
+ }
+
+ private void checkDirtyObjects()
+ {
+ final CDOID[] dirtyID = { null };
+ CDOReferenceAdjuster dirtyObjectChecker = new CDOReferenceAdjuster()
+ {
+ public Object adjustReference(Object targetID, EStructuralFeature feature, int index)
+ {
+ if (feature != CDOContainerFeatureDelta.CONTAINER_FEATURE)
+ {
+ if (detachedIDs.contains(targetID))
+ {
+ result.add(new CDOIDReference((CDOID)targetID, dirtyID[0], feature, index));
+ }
+
+ }
+
+ return targetID;
+ }
+ };
+
+ for (InternalCDORevision dirtyObject : dirtyObjects)
+ {
+ dirtyID[0] = dirtyObject.getID();
+ dirtyObject.adjustReferences(dirtyObjectChecker);
+ }
+ }
+
+ public long getTimeStamp()
+ {
+ return CDOBranchPoint.UNSPECIFIED_DATE;
+ }
+
+ public CDOBranch getBranch()
+ {
+ return transaction.getBranch();
+ }
+
+ public Map<CDOID, EClass> getTargetObjects()
+ {
+ return detachedObjectTypes;
+ }
+
+ public EReference[] getSourceReferences()
+ {
+ return new EReference[0];
+ }
+
+ public Map<EClass, List<EReference>> getSourceCandidates()
+ {
+ return sourceCandidates;
+ }
+
+ public int getMaxResults()
+ {
+ return CDOQueryInfo.UNLIMITED_RESULTS;
+ }
+
+ public boolean addXRef(CDOID targetID, CDOID sourceID, EReference sourceReference, int sourceIndex)
+ {
+ if (CDOIDUtil.isNull(targetID))
+ {
+ // Compensate potential issues with the XRef implementation in the store accessor.
+ return true;
+ }
+
+ if (detachedIDs.contains(sourceID))
+ {
+ // Ignore XRefs from objects that are about to be detached themselves by this commit.
+ return true;
+ }
+
+ if (dirtyIDs.contains(sourceID))
+ {
+ // Ignore XRefs from objects that are about to be modified by this commit. They're handled later in getXRefs().
+ return true;
+ }
+
+ result.add(new CDOIDReference(targetID, sourceID, sourceReference, sourceIndex));
+ return true;
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IPermissionManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IPermissionManager.java
new file mode 100644
index 0000000000..69f9d01f8d
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IPermissionManager.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2004 - 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;
+
+import org.eclipse.emf.cdo.common.security.CDOPermission;
+
+/**
+ * Provides the protection level of protectable objects in the context of a specific user.
+ *
+ * @author Eike Stepper
+ * @since 4.1
+ */
+public interface IPermissionManager
+{
+ public CDOPermission getPermission(Object protectableObject, String userID);
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java
index 44022132e2..73af757b30 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java
@@ -1,86 +1,87 @@
-/*
- * Copyright (c) 2004 - 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.spi.server;
-
-import org.eclipse.emf.cdo.common.CDOCommonRepository;
-import org.eclipse.emf.cdo.common.CDOCommonSession;
-import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDProvider;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.server.ISession;
-import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
-import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author Eike Stepper
- * @since 3.0
- * @noextend This interface is not intended to be extended by clients.
- * @noimplement This interface is not intended to be implemented by clients.
- */
-public interface InternalSession extends ISession, CDOIDProvider, CDOCommonSession.Options
-{
- public static final int TEMP_VIEW_ID = 0;
-
- public InternalSessionManager getManager();
-
- public InternalView[] getViews();
-
- public InternalView getView(int viewID);
-
- public InternalView openView(int viewID, CDOBranchPoint branchPoint);
-
- public InternalTransaction openTransaction(int viewID, CDOBranchPoint branchPoint);
-
- public void viewClosed(InternalView view);
-
- public void setSubscribed(boolean subscribed);
-
- public void collectContainedRevisions(InternalCDORevision revision, CDOBranchPoint branchPoint, int referenceChunk,
- Set<CDOID> revisions, List<CDORevision> additionalRevisions);
-
- public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType)
- throws Exception;
-
- /**
- * @deprecated use
- * {@link #sendRepositoryStateNotification(org.eclipse.emf.cdo.common.CDOCommonRepository.State, org.eclipse.emf.cdo.common.CDOCommonRepository.State, CDOID)}
- * instead
- */
- @Deprecated
- public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState)
- throws Exception;
-
- /**
- * @since 4.1
- */
- public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
- CDOID rootResourceID) throws Exception;
-
- public void sendBranchNotification(InternalCDOBranch branch) throws Exception;
-
- public void sendCommitNotification(CDOCommitInfo commitInfo) throws Exception;
-
- public void sendRemoteSessionNotification(InternalSession sender, byte opcode) throws Exception;
-
- public void sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message) throws Exception;
-
- /**
- * @since 4.1
- */
- public void sendLockNotification(CDOLockChangeInfo lockChangeInfo) throws Exception;
-}
+/*
+ * Copyright (c) 2004 - 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.spi.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.CDOCommonSession;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDProvider;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.security.CDOPermissionProvider;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalSession extends ISession, CDOIDProvider, CDOPermissionProvider, CDOCommonSession.Options
+{
+ public static final int TEMP_VIEW_ID = 0;
+
+ public InternalSessionManager getManager();
+
+ public InternalView[] getViews();
+
+ public InternalView getView(int viewID);
+
+ public InternalView openView(int viewID, CDOBranchPoint branchPoint);
+
+ public InternalTransaction openTransaction(int viewID, CDOBranchPoint branchPoint);
+
+ public void viewClosed(InternalView view);
+
+ public void setSubscribed(boolean subscribed);
+
+ public void collectContainedRevisions(InternalCDORevision revision, CDOBranchPoint branchPoint, int referenceChunk,
+ Set<CDOID> revisions, List<CDORevision> additionalRevisions);
+
+ public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType)
+ throws Exception;
+
+ /**
+ * @deprecated use
+ * {@link #sendRepositoryStateNotification(org.eclipse.emf.cdo.common.CDOCommonRepository.State, org.eclipse.emf.cdo.common.CDOCommonRepository.State, CDOID)}
+ * instead
+ */
+ @Deprecated
+ public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState)
+ throws Exception;
+
+ /**
+ * @since 4.1
+ */
+ public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
+ CDOID rootResourceID) throws Exception;
+
+ public void sendBranchNotification(InternalCDOBranch branch) throws Exception;
+
+ public void sendCommitNotification(CDOCommitInfo commitInfo) throws Exception;
+
+ public void sendRemoteSessionNotification(InternalSession sender, byte opcode) throws Exception;
+
+ public void sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message) throws Exception;
+
+ /**
+ * @since 4.1
+ */
+ public void sendLockNotification(CDOLockChangeInfo lockChangeInfo) throws Exception;
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java
index eb04653aab..aabf53ee71 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java
@@ -1,79 +1,95 @@
-/*
- * Copyright (c) 2004 - 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.spi.server;
-
-import org.eclipse.emf.cdo.common.CDOCommonRepository;
-import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.server.ISessionManager;
-import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
-import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
-
-import org.eclipse.net4j.util.security.IUserManager;
-
-import java.util.List;
-
-/**
- * @author Eike Stepper
- * @since 3.0
- * @noextend This interface is not intended to be extended by clients.
- * @noimplement This interface is not intended to be implemented by clients.
- */
-public interface InternalSessionManager extends ISessionManager
-{
- public InternalRepository getRepository();
-
- public void setRepository(InternalRepository repository);
-
- public void setUserManager(IUserManager userManager);
-
- public InternalSession[] getSessions();
-
- public InternalSession getSession(int sessionID);
-
- /**
- * @return Never <code>null</code>
- */
- public InternalSession openSession(ISessionProtocol sessionProtocol);
-
- public void sessionClosed(InternalSession session);
-
- public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType);
-
- /**
- * @deprecated use
- * {@link #sendRepositoryStateNotification(org.eclipse.emf.cdo.common.CDOCommonRepository.State, org.eclipse.emf.cdo.common.CDOCommonRepository.State, CDOID)}
- * instead
- */
- @Deprecated
- public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState);
-
- /**
- * @since 4.1
- */
- public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
- CDOID rootResourceID);
-
- public void sendBranchNotification(InternalSession sender, InternalCDOBranch branch);
-
- public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo);
-
- /**
- * @since 4.1
- */
- public void sendLockNotification(InternalSession sender, CDOLockChangeInfo lockChangeInfo);
-
- public void sendRemoteSessionNotification(InternalSession sender, byte opcode);
-
- public List<Integer> sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message,
- int[] recipients);
-}
+/*
+ * Copyright (c) 2004 - 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.spi.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.server.IPermissionManager;
+import org.eclipse.emf.cdo.server.ISessionManager;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+
+import org.eclipse.net4j.util.security.IUserManager;
+
+import java.util.List;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalSessionManager extends ISessionManager
+{
+ public InternalRepository getRepository();
+
+ public void setRepository(InternalRepository repository);
+
+ /**
+ * @since 4.1
+ */
+ public IUserManager getUserManager();
+
+ public void setUserManager(IUserManager userManager);
+
+ /**
+ * @since 4.1
+ */
+ public IPermissionManager getPermissionManager();
+
+ /**
+ * @since 4.1
+ */
+ public void setPermissionManager(IPermissionManager permissionManager);
+
+ public InternalSession[] getSessions();
+
+ public InternalSession getSession(int sessionID);
+
+ /**
+ * @return Never <code>null</code>
+ */
+ public InternalSession openSession(ISessionProtocol sessionProtocol);
+
+ public void sessionClosed(InternalSession session);
+
+ public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType);
+
+ /**
+ * @deprecated use
+ * {@link #sendRepositoryStateNotification(org.eclipse.emf.cdo.common.CDOCommonRepository.State, org.eclipse.emf.cdo.common.CDOCommonRepository.State, CDOID)}
+ * instead
+ */
+ @Deprecated
+ public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState);
+
+ /**
+ * @since 4.1
+ */
+ public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
+ CDOID rootResourceID);
+
+ public void sendBranchNotification(InternalSession sender, InternalCDOBranch branch);
+
+ public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo);
+
+ /**
+ * @since 4.1
+ */
+ public void sendLockNotification(InternalSession sender, CDOLockChangeInfo lockChangeInfo);
+
+ public void sendRemoteSessionNotification(InternalSession sender, byte opcode);
+
+ public List<Integer> sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message,
+ int[] recipients);
+}
diff --git a/plugins/org.eclipse.emf.cdo.tests.db/build.properties b/plugins/org.eclipse.emf.cdo.tests.db/build.properties
index 65455211eb..d3d1d56ff7 100644
--- a/plugins/org.eclipse.emf.cdo.tests.db/build.properties
+++ b/plugins/org.eclipse.emf.cdo.tests.db/build.properties
@@ -1,31 +1,34 @@
-# Copyright (c) 2004 - 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
-
-bin.includes = .,\
- META-INF/,\
- plugin.properties,\
- copyright.txt,\
- about.html,\
- .options
-jars.compile.order = .
-source.. = src/
-output.. = bin/
-src.includes = about.html,\
- copyright.txt,\
- CDO AllTests (DB2 non-audit).launch,\
- CDO AllTests (Derby).launch,\
- CDO AllTests (H2 audit).launch,\
- CDO AllTests (H2 branching).launch,\
- CDO AllTests (H2 non-audit).launch,\
- CDO AllTests (H2 offline).launch,\
- CDO AllTests (Hsqldb audit).launch,\
- CDO AllTests (Hsqldb non-audit).launch,\
- CDO AllTests (Mysql).launch,\
- CDO AllTests (PostgreSQL non-audit).launch,\
- CDO AllTests (DBStore).launch
+# Copyright (c) 2004 - 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
+
+bin.includes = .,\
+ META-INF/,\
+ plugin.properties,\
+ copyright.txt,\
+ about.html,\
+ .options
+jars.compile.order = .
+source.. = src/
+output.. = bin/
+src.includes = about.html,\
+ copyright.txt,\
+ CDO AllTests (DB2 non-audit).launch,\
+ CDO AllTests (Derby).launch,\
+ CDO AllTests (H2 audit).launch,\
+ CDO AllTests (H2 branching).launch,\
+ CDO AllTests (H2 non-audit).launch,\
+ CDO AllTests (H2 offline).launch,\
+ CDO AllTests (Hsqldb audit).launch,\
+ CDO AllTests (Hsqldb non-audit).launch,\
+ CDO AllTests (Mysql).launch,\
+ CDO AllTests (PostgreSQL non-audit).launch,\
+ CDO AllTests (DBStore).launch,\
+ CDO AllTests (H2 ALL).launch,\
+ CDO AllTests (H2 UUIDs).launch,\
+ CDO Performance Tests (H2 non-audit).launch
diff --git a/plugins/org.eclipse.emf.cdo.tests.db4o/build.properties b/plugins/org.eclipse.emf.cdo.tests.db4o/build.properties
index 5f4117fa8e..54175284a4 100644
--- a/plugins/org.eclipse.emf.cdo.tests.db4o/build.properties
+++ b/plugins/org.eclipse.emf.cdo.tests.db4o/build.properties
@@ -1,21 +1,22 @@
-# Copyright (c) 2004 - 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
-
-# NLS_MESSAGEFORMAT_VAR
-
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .,\
- copyright.txt,\
- about.html,\
- plugin.properties
-src.includes = about.html,\
- CDO AllTests (DB4O).launch,\
- copyright.txt
+# Copyright (c) 2004 - 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
+
+# NLS_MESSAGEFORMAT_VAR
+
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ copyright.txt,\
+ about.html,\
+ plugin.properties
+src.includes = about.html,\
+ CDO AllTests (DB4O).launch,\
+ copyright.txt,\
+ CDO AllTests (MEMDB4O).launch
diff --git a/plugins/org.eclipse.emf.cdo.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.tests/META-INF/MANIFEST.MF
index aaf6b433e7..c94d9103c0 100644
--- a/plugins/org.eclipse.emf.cdo.tests/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.tests/META-INF/MANIFEST.MF
@@ -33,7 +33,8 @@ Require-Bundle: org.eclipse.net4j.tests;bundle-version="[4.0.0,5.0.0)";visibilit
org.eclipse.emf.cdo.defs;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
org.eclipse.emf.cdo.server.ocl;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
org.eclipse.emf.cdo.workspace;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
- org.eclipse.gmf.runtime.notation;bundle-version="[1.5.0,2.0.0)";visibility:=reexport
+ org.eclipse.gmf.runtime.notation;bundle-version="[1.5.0,2.0.0)";visibility:=reexport,
+ org.eclipse.ocl.ecore;bundle-version="[3.0.0,4.0.0)"
Import-Package: org.apache.derby.jdbc;version="[10.0.0,11.0.0)",
org.h2.jdbcx;version="[1.0.0,2.0.0)"
Export-Package: base;version="4.0.100";
diff --git a/plugins/org.eclipse.emf.cdo.tests/build.properties b/plugins/org.eclipse.emf.cdo.tests/build.properties
index ab8efcc53c..900c2988b8 100644
--- a/plugins/org.eclipse.emf.cdo.tests/build.properties
+++ b/plugins/org.eclipse.emf.cdo.tests/build.properties
@@ -1,49 +1,39 @@
-# Copyright (c) 2004 - 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
-
-bin.includes = .,\
- model/,\
- META-INF/,\
- plugin.xml,\
- plugin.properties,\
- copyright.txt,\
- about.html,\
- about.ini,\
- about.mappings,\
- about.properties,\
- defs/,\
- ecore/,\
- model1.ecore,\
- modeling32.png,\
- model2.ecore,\
- test.xml,\
- uml2/,\
- My.ecore,\
- .options,\
- sslKey/,\
- SubclassTest1.ecore,\
- SubclassTest2.ecore,\
- logic/
-jars.compile.order = .
-source.. = src/,\
- model/
-output.. = bin/
-src.includes = about.html,\
- copyright.txt,\
- launches/CDO AllTests (MEM audit).launch,\
- launches/CDO AllTests (MEM branching SSL).launch,\
- launches/CDO AllTests (MEM branching TCP).launch,\
- launches/CDO AllTests (MEM branching UUIDs).launch,\
- launches/CDO AllTests (MEM branching).launch,\
- launches/CDO AllTests (MEM embedded).launch,\
- launches/CDO AllTests (MEM legacy).launch,\
- launches/CDO AllTests (MEM non-audit).launch,\
- launches/CDO AllTests (MEM offline).launch,\
- launches/CDO AllTests.launch,\
- launches/CDO PerformanceTests.launch
+# Copyright (c) 2004 - 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
+
+bin.includes = .,\
+ model/,\
+ META-INF/,\
+ plugin.xml,\
+ plugin.properties,\
+ copyright.txt,\
+ about.html,\
+ about.ini,\
+ about.mappings,\
+ about.properties,\
+ defs/,\
+ ecore/,\
+ model1.ecore,\
+ modeling32.png,\
+ model2.ecore,\
+ test.xml,\
+ uml2/,\
+ My.ecore,\
+ .options,\
+ sslKey/,\
+ SubclassTest1.ecore,\
+ SubclassTest2.ecore,\
+ logic/
+jars.compile.order = .
+source.. = src/,\
+ model/
+output.. = bin/
+src.includes = about.html,\
+ copyright.txt,\
+ launches/
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_343084_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_343084_Test.java
new file mode 100644
index 0000000000..bc6f93ce26
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_343084_Test.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2004 - 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.tests.bugzilla;
+
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.security.CDOPermission;
+import org.eclipse.emf.cdo.common.security.NoPermissionException;
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.server.IPermissionManager;
+import org.eclipse.emf.cdo.session.CDOSession;
+import org.eclipse.emf.cdo.tests.AbstractCDOTest;
+import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.CleanRepositoriesAfter;
+import org.eclipse.emf.cdo.tests.config.impl.ModelConfig;
+import org.eclipse.emf.cdo.tests.config.impl.RepositoryConfig;
+import org.eclipse.emf.cdo.tests.config.impl.SessionConfig;
+import org.eclipse.emf.cdo.tests.model1.Category;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.util.CDOUtil;
+
+import org.eclipse.net4j.util.security.PasswordCredentials;
+import org.eclipse.net4j.util.security.PasswordCredentialsProvider;
+import org.eclipse.net4j.util.security.UserManager;
+
+import org.eclipse.emf.ecore.EClass;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+@CleanRepositoriesAfter
+public class Bugzilla_343084_Test extends AbstractCDOTest
+{
+ private static final String REPO_NAME = "protectedrepo";
+
+ private static final String USER_ID = "stepper";
+
+ private static final char[] PASSWORD = "eike2010".toCharArray();
+
+ private Map<EClass, CDOPermission> permissions = new HashMap<EClass, CDOPermission>();
+
+ @Override
+ protected void doSetUp() throws Exception
+ {
+ super.doSetUp();
+
+ UserManager userManager = new UserManager();
+ userManager.activate();
+ userManager.addUser(USER_ID, PASSWORD);
+
+ IPermissionManager permissionManager = new IPermissionManager()
+ {
+ public CDOPermission getPermission(Object protectableObject, String userID)
+ {
+ if (protectableObject instanceof CDORevision)
+ {
+ EClass eClass = ((CDORevision)protectableObject).getEClass();
+ CDOPermission permission = permissions.get(eClass);
+ if (permission != null)
+ {
+ return permission;
+ }
+ }
+
+ return CDOPermission.WRITE;
+ }
+ };
+
+ getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager);
+ getTestProperties().put(RepositoryConfig.PROP_TEST_PERMISSION_MANAGER, permissionManager);
+ getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER,
+ new PasswordCredentialsProvider(new PasswordCredentials(USER_ID, PASSWORD)));
+
+ getRepository(REPO_NAME);
+ }
+
+ public void testPermissionManagerWRITE() throws Exception
+ {
+ {
+ CDOSession session = openSession(REPO_NAME);
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.createResource(getResourcePath("res"));
+
+ Category category = getModel1Factory().createCategory();
+ category.getCategories().add(getModel1Factory().createCategory());
+
+ resource.getContents().add(category);
+ transaction.commit();
+ session.close();
+ }
+
+ permissions.put(getModel1Package().getCategory(), CDOPermission.WRITE);
+
+ CDOSession session = openSession(REPO_NAME);
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.getResource(getResourcePath("res"));
+
+ Category category = (Category)resource.getContents().get(0);
+ CDORevision revision = CDOUtil.getCDOObject(category).cdoRevision();
+ assertEquals(CDOPermission.WRITE, revision.getPermission());
+ assertEquals(true, revision.isReadable());
+ assertEquals(true, revision.isWritable());
+
+ category.getName();
+ category.setName("HW");
+
+ category.getCategories().get(0);
+ category.getCategories().add(getModel1Factory().createCategory());
+ }
+
+ public void testPermissionManagerREAD() throws Exception
+ {
+ {
+ CDOSession session = openSession(REPO_NAME);
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.createResource(getResourcePath("res"));
+
+ Category category = getModel1Factory().createCategory();
+ category.getCategories().add(getModel1Factory().createCategory());
+
+ resource.getContents().add(category);
+ transaction.commit();
+ session.close();
+ }
+
+ permissions.put(getModel1Package().getCategory(), CDOPermission.READ);
+
+ CDOSession session = openSession(REPO_NAME);
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.getResource(getResourcePath("res"));
+
+ Category category = (Category)resource.getContents().get(0);
+ CDORevision revision = CDOUtil.getCDOObject(category).cdoRevision();
+ assertEquals(CDOPermission.READ, revision.getPermission());
+ assertEquals(true, revision.isReadable());
+ assertEquals(false, revision.isWritable());
+
+ category.getName();
+
+ try
+ {
+ category.setName("HW");
+ fail("NoPermissionException expected");
+ }
+ catch (NoPermissionException expected)
+ {
+ // SUCCESS
+ }
+
+ category.getCategories().get(0);
+
+ try
+ {
+ category.getCategories().add(getModel1Factory().createCategory());
+ fail("NoPermissionException expected");
+ }
+ catch (NoPermissionException expected)
+ {
+ // SUCCESS
+ }
+ }
+
+ @Skips(ModelConfig.CAPABILITY_LEGACY)
+ public void testPermissionManagerNONE() throws Exception
+ {
+ {
+ CDOSession session = openSession(REPO_NAME);
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.createResource(getResourcePath("res"));
+
+ Category category = getModel1Factory().createCategory();
+ category.getCategories().add(getModel1Factory().createCategory());
+
+ resource.getContents().add(category);
+ transaction.commit();
+ session.close();
+ }
+
+ permissions.put(getModel1Package().getCategory(), CDOPermission.NONE);
+
+ CDOSession session = openSession(REPO_NAME);
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.getResource(getResourcePath("res"));
+
+ Category category = (Category)resource.getContents().get(0);
+ CDORevision revision = CDOUtil.getCDOObject(category).cdoRevision();
+ assertEquals(CDOPermission.NONE, revision.getPermission());
+ assertEquals(false, revision.isReadable());
+ assertEquals(false, revision.isWritable());
+
+ try
+ {
+ category.getName();
+ fail("NoPermissionException expected");
+ }
+ catch (NoPermissionException expected)
+ {
+ // SUCCESS
+ }
+
+ try
+ {
+ category.setName("HW");
+ fail("NoPermissionException expected");
+ }
+ catch (NoPermissionException expected)
+ {
+ // SUCCESS
+ }
+
+ try
+ {
+ category.getCategories().get(0);
+ fail("NoPermissionException expected");
+ }
+ catch (NoPermissionException expected)
+ {
+ // SUCCESS
+ }
+
+ try
+ {
+ category.getCategories().add(getModel1Factory().createCategory());
+ fail("NoPermissionException expected");
+ }
+ catch (NoPermissionException expected)
+ {
+ // SUCCESS
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java
index e64f1c7573..69c45035b5 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java
@@ -24,6 +24,7 @@ import org.eclipse.emf.cdo.internal.server.syncing.RepositorySynchronizer;
import org.eclipse.emf.cdo.net4j.CDONet4jSessionConfiguration;
import org.eclipse.emf.cdo.server.CDOServerBrowser;
import org.eclipse.emf.cdo.server.CDOServerUtil;
+import org.eclipse.emf.cdo.server.IPermissionManager;
import org.eclipse.emf.cdo.server.IQueryHandlerProvider;
import org.eclipse.emf.cdo.server.IRepository;
import org.eclipse.emf.cdo.server.IRepository.Handler;
@@ -91,6 +92,8 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf
public static final String PROP_TEST_USER_MANAGER = "test.repository.UserManager";
+ public static final String PROP_TEST_PERMISSION_MANAGER = "test.repository.PermissionManager";
+
public static final String PROP_TEST_QUERY_HANDLER_PROVIDER = "test.repository.QueryHandlerProvider";
private static final boolean LOG_MULTI_VIEW_COMMIT = false;
@@ -492,7 +495,12 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf
if (userManager != null)
{
sessionManager.setUserManager(userManager);
- repository.setSessionManager(sessionManager);
+ }
+
+ IPermissionManager permissionManager = getTestPermissionManager();
+ if (permissionManager != null)
+ {
+ sessionManager.setPermissionManager(permissionManager);
}
IQueryHandlerProvider queryHandlerProvider = getTestQueryHandlerProvider();
@@ -524,6 +532,11 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf
return (IUserManager)getTestProperty(PROP_TEST_USER_MANAGER);
}
+ protected IPermissionManager getTestPermissionManager()
+ {
+ return (IPermissionManager)getTestProperty(PROP_TEST_PERMISSION_MANAGER);
+ }
+
protected IQueryHandlerProvider getTestQueryHandlerProvider()
{
return (IQueryHandlerProvider)getTestProperty(PROP_TEST_QUERY_HANDLER_PROVIDER);
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 cbb116fbf9..1d93cabcbd 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
@@ -1,1140 +1,1158 @@
-/*
- * Copyright (c) 2004 - 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
- * Martin Fluegge - bug 247226: Transparently support legacy models
- */
-package org.eclipse.emf.internal.cdo.object;
-
-import org.eclipse.emf.cdo.CDOObject;
-import org.eclipse.emf.cdo.CDOState;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.model.CDOModelUtil;
-import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
-import org.eclipse.emf.cdo.common.model.CDOType;
-import org.eclipse.emf.cdo.common.model.EMFUtil;
-import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
-import org.eclipse.emf.cdo.common.revision.CDOElementProxy;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionData;
-import org.eclipse.emf.cdo.common.util.CDOException;
-import org.eclipse.emf.cdo.eresource.CDOResource;
-import org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
-import org.eclipse.emf.cdo.util.CDOUtil;
-
-import org.eclipse.emf.internal.cdo.CDOObjectImpl;
-import org.eclipse.emf.internal.cdo.bundle.OM;
-import org.eclipse.emf.internal.cdo.view.CDOStateMachine;
-
-import org.eclipse.net4j.util.ReflectUtil;
-import org.eclipse.net4j.util.WrappedException;
-import org.eclipse.net4j.util.om.trace.ContextTracer;
-
-import org.eclipse.emf.common.notify.Adapter;
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.EAttribute;
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EClassifier;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.InternalEObject;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.util.InternalEList;
-import org.eclipse.emf.spi.cdo.CDOStore;
-import org.eclipse.emf.spi.cdo.FSMUtil;
-import org.eclipse.emf.spi.cdo.InternalCDOObject;
-import org.eclipse.emf.spi.cdo.InternalCDOView;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author Eike Stepper
- * @author Martin Fluegge
- * @since 2.0
- */
-public abstract class CDOLegacyWrapper extends CDOObjectWrapper
-{
- private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_OBJECT, CDOLegacyWrapper.class);
-
- /**
- * This ThreadLocal map stores all pre-registered objects. This avoids a never-ending loop when setting the container
- * of an object.
- */
- private static ThreadLocal<Map<CDOID, CDOLegacyWrapper>> wrapperRegistry = new InheritableThreadLocal<Map<CDOID, CDOLegacyWrapper>>()
- {
- @Override
- protected Map<CDOID, CDOLegacyWrapper> initialValue()
- {
- return new HashMap<CDOID, CDOLegacyWrapper>();
- }
- };
-
- private static ThreadLocal<Counter> recursionCounter = new InheritableThreadLocal<Counter>()
- {
- @Override
- protected Counter initialValue()
- {
- return new Counter();
- }
- };
-
- protected CDOState state;
-
- protected InternalCDORevision revision;
-
- /**
- * It could happen that while <i>revisionToInstance()</i> is executed externally the <i>internalPostLoad()</i> method
- * will be called. This happens for example if <i>internalPostInvalidate()</i> is called. The leads to another
- * <i>revisionToInstance()</i> call while the first call has not finished. This is certainly not so cool. That's why
- * <b>underConstruction</b> will flag that <i>revisionToInstance()</i> is still running and avoid the second call.
- *
- * @since 3.0
- */
- private boolean underConstruction;
-
- public CDOLegacyWrapper(InternalEObject instance)
- {
- this.instance = instance;
- state = CDOState.TRANSIENT;
- }
-
- public CDOState cdoState()
- {
- return state;
- }
-
- public InternalCDORevision cdoRevision()
- {
- return revision;
- }
-
- @Override
- public CDOResourceImpl cdoResource()
- {
- revisionToInstanceResource();
- return super.cdoResource();
- }
-
- public void cdoReload()
- {
- CDOStateMachine.INSTANCE.reload(this);
- }
-
- public CDOState cdoInternalSetState(CDOState state)
- {
- if (this.state != state)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Setting state {0} for {1}", state, this); //$NON-NLS-1$
- }
-
- CDOState oldState = this.state;
- this.state = state;
- adjustEProxy();
-
- if (view != null)
- {
- view.handleObjectStateChanged(this, oldState, state);
- }
-
- return oldState;
- }
-
- return null;
- }
-
- public void cdoInternalSetRevision(CDORevision revision)
- {
- if (TRACER.isEnabled())
- {
- TRACER.trace("Setting revision: " + revision); //$NON-NLS-1$
- }
-
- this.revision = (InternalCDORevision)revision;
- }
-
- public void cdoInternalPostAttach()
- {
- instanceToRevision();
-
- for (Adapter adapter : eAdapters())
- {
- if (!(adapter instanceof CDOObjectWrapper))
- {
- view.handleAddAdapter(this, adapter);
- view.subscribe(this, adapter);
- }
- }
- }
-
- public void cdoInternalPostDetach(boolean remote)
- {
- if (remote)
- {
- // Do nothing??
- return;
- }
-
- EClass eClass = revision.getEClass();
-
- // This loop adjusts the opposite wrapper objects to support dangling references. See Bugzilla_251263_Test
- for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass))
- {
- EReference oppositeReference = ((EStructuralFeature.Internal)feature).getEOpposite();
- if (oppositeReference != null && !oppositeReference.isContainment() && EMFUtil.isPersistent(oppositeReference))
- {
- if (feature.isMany())
- {
- int size = revision.size(feature);
- for (int i = 0; i < size; i++)
- {
- EObject object = (EObject)getValueFromRevision(feature, i);
- adjustPersistentOppositeReference(this, object, oppositeReference);
- }
- }
- else
- {
- EObject oppositeObject = (EObject)instance.eGet(feature);
- if (oppositeObject != null)
- {
- adjustPersistentOppositeReference(this, oppositeObject, oppositeReference);
- }
- }
- }
- }
- }
-
- /**
- * @since 3.0
- */
- public void cdoInternalPostRollback()
- {
- CDOStateMachine.INSTANCE.read(this);
- }
-
- /**
- * CDO persists the isUnset state of an eObject in the database. The indicator for this is that the feature is null in
- * the revision (see CDOStore.isSet()). When committing a legacy object all values in the instance for native
- * attributes are set with the java default values. So, these values will be stored in the revision and CDO cannot
- * distinguish whether the feature is set or not. This method must ensure that the value will be set to null if the
- * feature is not set.
- */
- public void cdoInternalPreCommit()
- {
- // We have to set this here because the CDOLegacyAdapter will not be notified when the instance is the target of a
- // single-directional containment reference.
- // If the container is not an legacy Object the system will get no information
- instanceToRevisionContainment();
-
- EClass eClass = revision.getEClass();
- for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass))
- {
- if (feature.isUnsettable())
- {
- if (!instance.eIsSet(feature))
- {
- if (feature.isMany())
- {
- @SuppressWarnings("unchecked")
- InternalEList<Object> list = (InternalEList<Object>)instance.eGet(feature);
- clearEList(list);
- }
- else
- {
- revision.set(feature, EStore.NO_INDEX, null);
- }
- }
- else if (instance.eGet(feature) == null)
- {
- // Must be single-valued!
- revision.set(feature, EStore.NO_INDEX, CDORevisionData.NIL);
- }
- }
- }
- }
-
- public void cdoInternalPreLoad()
- {
- // Do nothing
- }
-
- public void cdoInternalPostLoad()
- {
- // TODO Consider not remembering the revision after copying it to the instance (spare 1/2 of the space)
- revisionToInstance();
- }
-
- public void cdoInternalPostInvalidate()
- {
- if (cdoState() != CDOState.CLEAN)
- {
- InternalCDORevision revision = cdoView().getRevision(cdoID(), true);
- cdoInternalSetRevision(revision);
- }
-
- revisionToInstance();
- cdoInternalSetState(CDOState.CLEAN);
- }
-
- @Override
- public boolean equals(Object obj)
- {
- return obj == this || obj == instance;
- }
-
- @Override
- public int hashCode()
- {
- if (instance != null)
- {
- return instance.hashCode();
- }
-
- return super.hashCode();
- }
-
- @Override
- public String toString()
- {
- return "CDOLegacyWrapper[" + instance.getClass().getSimpleName() + "@" + id + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- protected void instanceToRevision()
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Transfering instance to revision: {0} --> {1}", instance, revision); //$NON-NLS-1$
- }
-
- // Handle containment
- instanceToRevisionContainment();
-
- // Handle values
- CDOPackageRegistry packageRegistry = cdoView().getSession().getPackageRegistry();
- EClass eClass = revision.getEClass();
- for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass))
- {
- instanceToRevisionFeature(feature, packageRegistry);
- }
- }
-
- protected void instanceToRevisionContainment()
- {
- CDOResource resource = (CDOResource)getInstanceResource(instance);
- revision.setResourceID(resource == null ? CDOID.NULL : resource.cdoID());
-
- InternalEObject eContainer = getInstanceContainer(instance);
- if (eContainer == null)
- {
- revision.setContainerID(CDOID.NULL);
- revision.setContainingFeatureID(0);
- }
- else
- {
- CDOObject cdoContainer = FSMUtil.adapt(eContainer, view);
- revision.setContainerID(cdoContainer);
- revision.setContainingFeatureID(getInstanceContainerFeatureID(instance));
- }
- }
-
- protected void instanceToRevisionFeature(EStructuralFeature feature, CDOPackageRegistry packageRegistry)
- {
- Object instanceValue = getInstanceValue(instance, feature, packageRegistry);
- CDOObjectImpl.instanceToRevisionFeature(view, this, feature, instanceValue);
- }
-
- protected void revisionToInstance()
- {
- if (underConstruction)
- {
- // Return if revisionToInstance was called before to avoid doubled calls
- return;
- }
-
- underConstruction = true;
-
- if (TRACER.isEnabled())
- {
- TRACER.format("Transfering revision to instance: {0} --> {1}", revision, instance); //$NON-NLS-1$
- }
-
- boolean deliver = instance.eDeliver();
- if (deliver)
- {
- instance.eSetDeliver(false);
- }
-
- Counter counter = recursionCounter.get();
- try
- {
- registerWrapper(this);
- counter.increment();
- view.registerObject(this);
-
- revisionToInstanceContainer();
-
- for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(revision.getEClass()))
- {
- revisionToInstanceFeature(feature);
- }
-
- revisionToInstanceResource();
- }
- catch (RuntimeException ex)
- {
- OM.LOG.error(ex);
- throw ex;
- }
- catch (Exception ex)
- {
- OM.LOG.error(ex);
- throw new CDOException(ex);
- }
- finally
- {
- if (deliver)
- {
- instance.eSetDeliver(true);
- }
-
- counter.decrement();
- unregisterWrapper(this);
- underConstruction = false;
- }
- }
-
- /**
- * @since 4.0
- */
- protected void revisionToInstanceContainer()
- {
- Object containerID = revision.getContainerID();
- InternalEObject container = getEObjectFromPotentialID(view, null, containerID);
-
- EObject oldContainer = instance.eContainer();
- if (oldContainer != container)
- {
- setInstanceContainer(container, revision.getContainingFeatureID());
- }
- }
-
- /**
- * @since 4.0
- */
- protected void revisionToInstanceResource()
- {
- if (revision != null)
- {
- CDOID resourceID = revision.getResourceID();
- InternalEObject resource = getEObjectFromPotentialID(view, null, resourceID);
- setInstanceResource((Resource.Internal)resource);
- if (resource != null)
- {
- view.registerObject((InternalCDOObject)resource);
- }
- }
- }
-
- /**
- * @since 3.0
- */
- protected void revisionToInstanceFeature(EStructuralFeature feature)
- {
- if (feature.isUnsettable() && !view.getStore().isSet(this, feature))
- {
- // Clarify if this is sufficient for bidirectional references
- instance.eUnset(feature);
- return;
- }
-
- if (feature.isMany())
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("State of Object (" + this + "/" + instance + ") is : " + state); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- if (state == CDOState.CLEAN || state == CDOState.PROXY || state == CDOState.NEW || state == CDOState.DIRTY)
- {
- int size = revision.size(feature);
-
- @SuppressWarnings("unchecked")
- InternalEList<Object> list = (InternalEList<Object>)instance.eGet(feature);
-
- clearEList(list);
- for (int i = 0; i < size; i++)
- {
- Object object = getValueFromRevision(feature, i);
-
- if (TRACER.isEnabled())
- {
- TRACER.format("Adding " + object + " to feature " + feature + "in instance " + instance); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- list.basicAdd(object, null);
- }
- }
- }
- else
- {
- // !feature.isMany()
- Object object = getValueFromRevision(feature, 0);
- if (feature instanceof EAttribute)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Setting attribute value " + object + " to feature " + feature + " in instance " + instance); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- // Just fake it for the store :(
- if (feature.isUnsettable() && object.equals(CDORevisionData.NIL))
- {
- eSet(feature, null);
- }
- else
- {
- eSet(feature, object);
- }
- }
- else
- {
- // EReferences
- if (TRACER.isEnabled())
- {
- TRACER.format("Adding object " + object + " to feature " + feature + " in instance " + instance); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- int featureID = instance.eClass().getFeatureID(feature);
- Class<? extends Object> baseClass = object == null ? null : object.getClass();
- EStructuralFeature.Internal internalFeature = (EStructuralFeature.Internal)feature;
- EReference oppositeReference = internalFeature.getEOpposite();
-
- if (oppositeReference != null)
- {
- if (object != null)
- {
- // If you have a containment reference but the container is not set, but the object is attached to a
- // resource
- // do not set the feature to null. Otherwise the object will be removed from the container which is the
- // resource instead of the original container. As a result the object will be detached. See
- // MapTest.testEObjectToEObjectValueContainedMap for more information
- if (object != instance.eContainer())
- {
- instance.eInverseAdd((InternalEObject)object, featureID, baseClass, null);
- }
-
- if (!EMFUtil.isPersistent(oppositeReference))
- {
- adjustTransientOppositeReference(instance, (InternalEObject)object, oppositeReference);
- }
- }
- }
- else
- {
- if (object != CDORevisionData.NIL)
- {
- EReference reference = (EReference)feature;
- if (reference.isContainment())
- {
- if (object != null)
- {
- // Calling eSet it not the optimal approach, but currently there is no other way to set the value here.
- // To avoid attaching already processed (clean) objects a check was introduced to
- // CDOResourceImpl.attached(EObject).
- // If we find a way to avoid the call of eSet and if we are able to only set the feature value directly
- // this check can be removed from CDOResourceImpl. See also Bug 352204.
- instance.eSet(feature, object);
- }
- else
- {
- instance.eSet(feature, null);
- }
- }
- else
- {
- instance.eSet(feature, object);
- }
- }
- else
- {
- instance.eSet(feature, null);
- }
- }
-
- if (TRACER.isEnabled())
- {
- TRACER.format("Added object " + object + " to feature " + feature + " in instance " + instance); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
- }
- }
- }
-
- /**
- * This method retrieves the value from the feature at the given index. It retrieves the value either from the views's
- * store or the internal pre-registration Map.
- *
- * @param feature
- * the feature to retrieve the value from
- * @param index
- * the given index of the object in the feature
- * @return the value from the feature at the given index
- */
- private Object getValueFromRevision(EStructuralFeature feature, int index)
- {
- Object object = revision.get(feature, index);
- if (object == null)
- {
- return null;
- }
-
- if (object instanceof CDOElementProxy)
- {
- // Resolve proxy
- CDOElementProxy proxy = (CDOElementProxy)object;
- object = view.getSession().resolveElementProxy(revision, feature, index, proxy.getIndex());
- }
-
- if (object instanceof CDOLegacyWrapper)
- {
- return ((CDOLegacyWrapper)object).cdoInternalInstance();
- }
-
- CDOType type = CDOModelUtil.getType(feature.getEType());
- object = view.getStore().convertToEMF(instance, revision, feature, index, object);
-
- if (type == CDOType.OBJECT)
- {
- if (object instanceof CDOID)
- {
- CDOID id = (CDOID)object;
- if (id.isNull())
- {
- return null;
- }
-
- object = getRegisteredWrapper(id);
- if (object != null)
- {
- return ((CDOLegacyWrapper)object).cdoInternalInstance();
- }
-
- if (id.isExternal())
- {
- object = view.getResourceSet().getEObject(URI.createURI(id.toURIFragment()), true);
- }
- else
- {
- object = view.getObject(id);
- }
-
- if (object instanceof CDOObjectWrapper)
- {
- return ((CDOObjectWrapper)object).cdoInternalInstance();
- }
- }
- }
-
- return object;
- }
-
- protected Resource.Internal getInstanceResource(InternalEObject instance)
- {
- return instance.eDirectResource();
- }
-
- protected InternalEObject getInstanceContainer(InternalEObject instance)
- {
- return instance.eInternalContainer();
- }
-
- protected int getInstanceContainerFeatureID(InternalEObject instance)
- {
- return instance.eContainerFeatureID();
- }
-
- protected Object getInstanceValue(InternalEObject instance, EStructuralFeature feature,
- CDOPackageRegistry packageRegistry)
- {
- return instance.eGet(feature);
- }
-
- protected void setInstanceResource(Resource.Internal resource)
- {
- Method method = ReflectUtil.getMethod(instance.getClass(), "eSetDirectResource", Resource.Internal.class); //$NON-NLS-1$
- ReflectUtil.invokeMethod(method, instance, resource);
- }
-
- protected void setInstanceContainer(InternalEObject container, int containerFeatureID)
- {
- Method method = ReflectUtil.getMethod(instance.getClass(), "eBasicSetContainer", InternalEObject.class, int.class); //$NON-NLS-1$
- ReflectUtil.invokeMethod(method, instance, container, containerFeatureID);
- }
-
- protected void setInstanceValue(InternalEObject instance, EStructuralFeature feature, Object value)
- {
- instance.eSet(feature, value);
- }
-
- /**
- * @param feature
- * in case that a proxy has to be created the feature that will determine the interface type of the proxy and
- * that will be used later to resolve the proxy. <code>null</code> indicates that proxy creation will be
- * avoided!
- */
- protected InternalEObject getEObjectFromPotentialID(InternalCDOView view, EStructuralFeature feature,
- Object potentialID)
- {
- CDOLegacyWrapper wrapper;
- if (potentialID instanceof CDOID && (wrapper = getRegisteredWrapper((CDOID)potentialID)) != null)
- {
- potentialID = wrapper.instance;
-
- if (TRACER.isEnabled())
- {
- TRACER.format("Getting Object (" + potentialID + ") from localThread instead of the view"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
- else
- {
- if (potentialID instanceof CDOID)
- {
- CDOID id = (CDOID)potentialID;
- if (id.isNull())
- {
- return null;
- }
-
- if (id.isExternal())
- {
- URI uri = URI.createURI(id.toURIFragment());
- InternalEObject eObject = (InternalEObject)view.getResourceSet().getEObject(uri, true);
- return eObject;
- }
-
- boolean loadOnDemand = feature == null;
- potentialID = view.getObject(id, loadOnDemand);
- if (potentialID == null && !loadOnDemand)
- {
- return createProxy(view, feature, id);
- }
- }
-
- if (potentialID instanceof InternalCDOObject)
- {
- return ((InternalCDOObject)potentialID).cdoInternalInstance();
- }
- }
-
- return (InternalEObject)potentialID;
- }
-
- /**
- * Creates and returns a <em>proxy</em> object. The usage of a proxy object is strongly limited. The only guarantee
- * that can be made is that the following methods are callable and will behave in the expected way:
- * <ul>
- * <li>{@link CDOObject#cdoID()} will return the {@link CDOID} of the target object
- * <li>{@link CDOObject#cdoState()} will return {@link CDOState#PROXY PROXY}
- * <li>{@link InternalEObject#eIsProxy()} will return <code>true</code>
- * <li>{@link InternalEObject#eProxyURI()} will return the EMF proxy URI of the target object
- * </ul>
- * Calling any other method on the proxy object will result in an {@link UnsupportedOperationException} being thrown
- * at runtime. Note also that the proxy object might even not be cast to the concrete type of the target object. The
- * proxy can only guaranteed to be of <em>any</em> concrete subtype of the declared type of the given feature.
- * <p>
- * TODO {@link InternalEObject#eResolveProxy(InternalEObject)}
- */
- protected InternalEObject createProxy(InternalCDOView view, EStructuralFeature feature, CDOID id)
- {
- EClassifier eType = feature.getEType();
- Class<?> instanceClass = eType.getInstanceClass();
-
- Class<?>[] interfaces = { instanceClass, InternalEObject.class, LegacyProxy.class };
- ClassLoader classLoader = CDOLegacyWrapper.class.getClassLoader();
- LegacyProxyInvocationHandler handler = new LegacyProxyInvocationHandler(this, id);
- return (InternalEObject)Proxy.newProxyInstance(classLoader, interfaces, handler);
- }
-
- protected void clearEList(InternalEList<?> list)
- {
- for (int i = list.size() - 1; i >= 0; --i)
- {
- Object obj = list.get(i);
- list.basicRemove(obj, null);
- }
- }
-
- /**
- * TODO Consider using only EMF concepts for resolving proxies!
- */
- protected void resolveAllProxies()
- {
- CDOPackageRegistry packageRegistry = cdoView().getSession().getPackageRegistry();
- EClass eClass = revision.getEClass();
- for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass))
- {
- if (feature instanceof EReference)
- {
- resolveProxies(feature, packageRegistry);
- }
- }
- }
-
- /**
- * IMPORTANT: Compile errors in this method might indicate an old version of EMF. Legacy support is only enabled for
- * EMF with fixed bug #247130. These compile errors do not affect native models!
- */
- protected void resolveProxies(EStructuralFeature feature, CDOPackageRegistry packageRegistry)
- {
- Object value = getInstanceValue(instance, feature, packageRegistry);
- if (value != null)
- {
- if (feature.isMany())
- {
- @SuppressWarnings("unchecked")
- InternalEList<Object> list = (InternalEList<Object>)value;
- int size = list.size();
-
- boolean deliver = instance.eDeliver();
- if (deliver)
- {
- instance.eSetDeliver(false);
- }
-
- for (int i = 0; i < size; i++)
- {
- Object element = list.get(i);
- if (element instanceof LegacyProxy)
- {
- CDOID id = ((LegacyProxy)element).getID();
- InternalCDOObject resolved = (InternalCDOObject)view.getObject(id);
- InternalEObject instance = resolved.cdoInternalInstance();
-
- // TODO LEGACY
- // // TODO Is InternalEList.basicSet() needed???
- // if (list instanceof
- // org.eclipse.emf.ecore.util.DelegatingInternalEList)
- // {
- // list =
- // ((org.eclipse.emf.ecore.util.DelegatingInternalEList)list).getDelegateInternalEList();
- // }
-
- // if (list instanceof NotifyingListImpl<?>)
- // {
- // ((NotifyingListImpl<Object>)list).basicSet(i, instance, null);
- // }
- // else
- // {
- list.set(i, instance);
- // }
- }
- }
-
- if (deliver)
- {
- instance.eSetDeliver(true);
- }
- }
- else
- {
- if (value instanceof LegacyProxy)
- {
- CDOID id = ((LegacyProxy)value).getID();
- InternalCDOObject resolved = (InternalCDOObject)view.getObject(id);
- InternalEObject instance = resolved.cdoInternalInstance();
- setInstanceValue(instance, feature, instance);
- }
- }
- }
- }
-
- protected void adjustEProxy()
- {
- // Setting eProxyURI is necessary to prevent content adapters from
- // loading the whole content tree.
- // TODO Does not have the desired effect ;-( see CDOEditor.createModel()
- if (state == CDOState.PROXY)
- {
- if (!instance.eIsProxy())
- {
- URI uri = URI.createURI(CDOProtocolConstants.PROTOCOL_NAME + ":proxy#" + id); //$NON-NLS-1$
- if (TRACER.isEnabled())
- {
- TRACER.format("Setting proxyURI {0} for {1}", uri, instance); //$NON-NLS-1$
- }
-
- instance.eSetProxyURI(uri);
- }
- }
- else
- {
- if (instance.eIsProxy())
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Unsetting proxyURI for {0}", instance); //$NON-NLS-1$
- }
-
- instance.eSetProxyURI(null);
- }
- }
- }
-
- @Override
- public synchronized EList<Adapter> eAdapters()
- {
- EList<Adapter> adapters = instance.eAdapters();
- for (Adapter adapter : adapters)
- {
- if (!FSMUtil.isTransient(this) && !(adapter instanceof CDOLegacyWrapper))
- {
- cdoView().handleAddAdapter(this, adapter);
- }
- }
-
- return adapters;
- }
-
- public static boolean isLegacyProxy(Object object)
- {
- return object instanceof LegacyProxy;
- }
-
- protected static int getEFlagMask(Class<?> instanceClass, String flagName)
- {
- Field field = ReflectUtil.getField(instanceClass, flagName);
- if (!field.isAccessible())
- {
- field.setAccessible(true);
- }
-
- try
- {
- return (Integer)field.get(null);
- }
- catch (IllegalAccessException ex)
- {
- throw WrappedException.wrap(ex);
- }
- }
-
- /**
- * @since 3.0
- */
- protected static CDOLegacyWrapper getRegisteredWrapper(CDOID id)
- {
- return wrapperRegistry.get().get(id);
- }
-
- /**
- * Adds an object to the pre-registered objects list which hold all created objects even if they are not registered in
- * the view
- *
- * @since 3.0
- */
- protected static void registerWrapper(CDOLegacyWrapper wrapper)
- {
- wrapperRegistry.get().put(wrapper.cdoID(), wrapper);
- }
-
- /**
- * @since 3.0
- */
- protected static void unregisterWrapper(CDOLegacyWrapper wrapper)
- {
- wrapperRegistry.get().remove(wrapper.cdoID());
- }
-
- /**
- * @since 3.0
- */
- protected static boolean isRegisteredWrapper(CDOLegacyWrapper wrapper)
- {
- return wrapperRegistry.get().containsKey(wrapper.cdoID());
- }
-
- // TODO: Remove this method if it is ensured that ist is not needed anymore
- // private void adjustOppositeReference(InternalCDOObject cdoObject, EObject oppositeObject, EReference
- // oppositeReference)
- // {
- // if (oppositeObject != null)
- // {
- // InternalCDOObject oppositeCDOObject = (InternalCDOObject)CDOUtil.getCDOObject(oppositeObject);
- //
- // if (!FSMUtil.isTransient(oppositeCDOObject) && !EMFUtil.isPersistent(oppositeReference))
- // {
- // adjustPersistentOppositeReference(cdoObject, oppositeObject, oppositeReference);
- // }
- // else
- // {
- // if (oppositeReference.isResolveProxies())
- // {
- // adjustTransientOppositeReference(instance, (InternalEObject)oppositeObject, oppositeReference);
- // }
- // }
- // }
- // }
-
- private void adjustPersistentOppositeReference(InternalCDOObject cdoObject, EObject oppositeObject,
- EReference oppositeReference)
- {
- InternalCDOObject oppositeCDOObject = (InternalCDOObject)CDOUtil.getCDOObject(oppositeObject);
- if (oppositeCDOObject != null)
- {
- InternalCDOView view = oppositeCDOObject.cdoView();
- if (view != null)
- {
- CDOStore store = view.getStore();
- if (store != null)
- {
- if (oppositeReference.isMany())
- {
- EObject eObject = oppositeCDOObject.cdoInternalInstance();
-
- @SuppressWarnings("unchecked")
- EList<Object> list = (EList<Object>)eObject.eGet(oppositeReference);
- int index = list.indexOf(instance);
-
- if (!store.isEmpty(oppositeCDOObject, oppositeReference) && index != EStore.NO_INDEX)
- {
- store.set(oppositeCDOObject, oppositeReference, index, cdoObject);
- }
- }
- else
- {
- store.set(oppositeCDOObject, oppositeReference, 0, cdoObject);
- }
- }
- }
- }
- }
-
- private void adjustTransientOppositeReference(InternalEObject instance, InternalEObject object,
- EReference oppositeReference)
- {
- boolean wasDeliver = object.eDeliver(); // Disable notifications
- if (wasDeliver)
- {
- object.eSetDeliver(false);
- }
-
- try
- {
- if (oppositeReference.isMany())
- {
- @SuppressWarnings("unchecked")
- InternalEList<Object> list = (InternalEList<Object>)object.eGet(oppositeReference);
- list.basicAdd(instance, null);
- }
- else
- {
- if (object.eGet(oppositeReference) != instance)
- {
- object.eInverseAdd(instance, oppositeReference.getFeatureID(), ((EObject)instance).getClass(), null);
- }
- }
- }
- finally
- {
- if (wasDeliver)
- {
- object.eSetDeliver(true);
- }
- }
- }
-
- /**
- * @author Eike Stepper
- */
- private static interface LegacyProxy
- {
- public CDOID getID();
- }
-
- /**
- * @author Eike Stepper
- */
- private static final class LegacyProxyInvocationHandler implements InvocationHandler, LegacyProxy
- {
- private static final Method getIDMethod = ReflectUtil.getMethod(LegacyProxy.class, "getID"); //$NON-NLS-1$
-
- private static final Method eIsProxyMethod = ReflectUtil.getMethod(EObject.class, "eIsProxy"); //$NON-NLS-1$
-
- private static final Method eProxyURIMethod = ReflectUtil.getMethod(InternalEObject.class, "eProxyURI"); //$NON-NLS-1$
-
- private CDOLegacyWrapper wrapper;
-
- private CDOID id;
-
- public LegacyProxyInvocationHandler(CDOLegacyWrapper wrapper, CDOID id)
- {
- this.wrapper = wrapper;
- this.id = id;
- }
-
- public CDOID getID()
- {
- return id;
- }
-
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
- {
- if (method.equals(getIDMethod))
- {
- return id;
- }
-
- if (method.equals(eIsProxyMethod))
- {
- return true;
- }
-
- if (method.equals(eProxyURIMethod))
- {
- // Use container's resource because it's guaranteed to be in the same CDOView as the resource of the target!
- Resource resource = wrapper.eResource();
-
- // TODO Consider using a "fake" Resource implementation. See Resource.getEObject(...)
- return resource.getURI().appendFragment(id.toURIFragment());
- }
-
- // A client must have invoked the proxy while being told not to do so!
- throw new UnsupportedOperationException(method.getName());
- }
- }
-
- /**
- * @author Martin Fluegge
- */
- private static final class Counter
- {
- private int value;
-
- public Counter()
- {
- }
-
- public void increment()
- {
- ++value;
- }
-
- public int decrement()
- {
- return --value;
- }
- }
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Martin Fluegge - bug 247226: Transparently support legacy models
+ */
+package org.eclipse.emf.internal.cdo.object;
+
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.CDOState;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
+import org.eclipse.emf.cdo.common.model.CDOType;
+import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.revision.CDOElementProxy;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionData;
+import org.eclipse.emf.cdo.common.security.CDOPermission;
+import org.eclipse.emf.cdo.common.util.CDOException;
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.util.CDOUtil;
+
+import org.eclipse.emf.internal.cdo.CDOObjectImpl;
+import org.eclipse.emf.internal.cdo.bundle.OM;
+import org.eclipse.emf.internal.cdo.view.CDOStateMachine;
+
+import org.eclipse.net4j.util.ReflectUtil;
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.InternalEList;
+import org.eclipse.emf.spi.cdo.CDOStore;
+import org.eclipse.emf.spi.cdo.FSMUtil;
+import org.eclipse.emf.spi.cdo.InternalCDOObject;
+import org.eclipse.emf.spi.cdo.InternalCDOView;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ * @author Martin Fluegge
+ * @since 2.0
+ */
+public abstract class CDOLegacyWrapper extends CDOObjectWrapper
+{
+ private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_OBJECT, CDOLegacyWrapper.class);
+
+ /**
+ * This ThreadLocal map stores all pre-registered objects. This avoids a never-ending loop when setting the container
+ * of an object.
+ */
+ private static ThreadLocal<Map<CDOID, CDOLegacyWrapper>> wrapperRegistry = new InheritableThreadLocal<Map<CDOID, CDOLegacyWrapper>>()
+ {
+ @Override
+ protected Map<CDOID, CDOLegacyWrapper> initialValue()
+ {
+ return new HashMap<CDOID, CDOLegacyWrapper>();
+ }
+ };
+
+ private static ThreadLocal<Counter> recursionCounter = new InheritableThreadLocal<Counter>()
+ {
+ @Override
+ protected Counter initialValue()
+ {
+ return new Counter();
+ }
+ };
+
+ protected CDOState state;
+
+ protected InternalCDORevision revision;
+
+ /**
+ * It could happen that while <i>revisionToInstance()</i> is executed externally the <i>internalPostLoad()</i> method
+ * will be called. This happens for example if <i>internalPostInvalidate()</i> is called. The leads to another
+ * <i>revisionToInstance()</i> call while the first call has not finished. This is certainly not so cool. That's why
+ * <b>underConstruction</b> will flag that <i>revisionToInstance()</i> is still running and avoid the second call.
+ *
+ * @since 3.0
+ */
+ private boolean underConstruction;
+
+ public CDOLegacyWrapper(InternalEObject instance)
+ {
+ this.instance = instance;
+ state = CDOState.TRANSIENT;
+ }
+
+ public CDOState cdoState()
+ {
+ return state;
+ }
+
+ public InternalCDORevision cdoRevision()
+ {
+ return revision;
+ }
+
+ @Override
+ public CDOResourceImpl cdoResource()
+ {
+ revisionToInstanceResource();
+ return super.cdoResource();
+ }
+
+ public void cdoReload()
+ {
+ CDOStateMachine.INSTANCE.reload(this);
+ }
+
+ public CDOState cdoInternalSetState(CDOState state)
+ {
+ if (this.state != state)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting state {0} for {1}", state, this); //$NON-NLS-1$
+ }
+
+ CDOState oldState = this.state;
+ this.state = state;
+ adjustEProxy();
+
+ if (view != null)
+ {
+ view.handleObjectStateChanged(this, oldState, state);
+ }
+
+ return oldState;
+ }
+
+ return null;
+ }
+
+ public void cdoInternalSetRevision(CDORevision revision)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.trace("Setting revision: " + revision); //$NON-NLS-1$
+ }
+
+ this.revision = (InternalCDORevision)revision;
+ }
+
+ public void cdoInternalPostAttach()
+ {
+ instanceToRevision();
+
+ for (Adapter adapter : eAdapters())
+ {
+ if (!(adapter instanceof CDOObjectWrapper))
+ {
+ view.handleAddAdapter(this, adapter);
+ view.subscribe(this, adapter);
+ }
+ }
+ }
+
+ public void cdoInternalPostDetach(boolean remote)
+ {
+ if (remote)
+ {
+ // Do nothing??
+ return;
+ }
+
+ EClass eClass = revision.getEClass();
+
+ // This loop adjusts the opposite wrapper objects to support dangling references. See Bugzilla_251263_Test
+ for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass))
+ {
+ EReference oppositeReference = ((EStructuralFeature.Internal)feature).getEOpposite();
+ if (oppositeReference != null && !oppositeReference.isContainment() && EMFUtil.isPersistent(oppositeReference))
+ {
+ if (feature.isMany())
+ {
+ int size = revision.size(feature);
+ for (int i = 0; i < size; i++)
+ {
+ EObject object = (EObject)getValueFromRevision(feature, i);
+ adjustPersistentOppositeReference(this, object, oppositeReference);
+ }
+ }
+ else
+ {
+ EObject oppositeObject = (EObject)instance.eGet(feature);
+ if (oppositeObject != null)
+ {
+ adjustPersistentOppositeReference(this, oppositeObject, oppositeReference);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void cdoInternalPostRollback()
+ {
+ CDOStateMachine.INSTANCE.read(this);
+ }
+
+ /**
+ * CDO persists the isUnset state of an eObject in the database. The indicator for this is that the feature is null in
+ * the revision (see CDOStore.isSet()). When committing a legacy object all values in the instance for native
+ * attributes are set with the java default values. So, these values will be stored in the revision and CDO cannot
+ * distinguish whether the feature is set or not. This method must ensure that the value will be set to null if the
+ * feature is not set.
+ */
+ public void cdoInternalPreCommit()
+ {
+ // We have to set this here because the CDOLegacyAdapter will not be notified when the instance is the target of a
+ // single-directional containment reference.
+ // If the container is not an legacy Object the system will get no information
+ instanceToRevisionContainment();
+
+ EClass eClass = revision.getEClass();
+ for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass))
+ {
+ if (feature.isUnsettable())
+ {
+ if (!instance.eIsSet(feature))
+ {
+ if (feature.isMany())
+ {
+ @SuppressWarnings("unchecked")
+ InternalEList<Object> list = (InternalEList<Object>)instance.eGet(feature);
+ clearEList(list);
+ }
+ else
+ {
+ revision.set(feature, EStore.NO_INDEX, null);
+ }
+ }
+ else if (instance.eGet(feature) == null)
+ {
+ // Must be single-valued!
+ revision.set(feature, EStore.NO_INDEX, CDORevisionData.NIL);
+ }
+ }
+ }
+ }
+
+ public void cdoInternalPreLoad()
+ {
+ // Do nothing
+ }
+
+ public void cdoInternalPostLoad()
+ {
+ // TODO Consider not remembering the revision after copying it to the instance (spare 1/2 of the space)
+ revisionToInstance();
+ }
+
+ public void cdoInternalPostInvalidate()
+ {
+ if (cdoState() != CDOState.CLEAN)
+ {
+ InternalCDORevision revision = cdoView().getRevision(cdoID(), true);
+ cdoInternalSetRevision(revision);
+ }
+
+ revisionToInstance();
+ cdoInternalSetState(CDOState.CLEAN);
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ return obj == this || obj == instance;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ if (instance != null)
+ {
+ return instance.hashCode();
+ }
+
+ return super.hashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "CDOLegacyWrapper[" + instance.getClass().getSimpleName() + "@" + id + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ protected void instanceToRevision()
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Transfering instance to revision: {0} --> {1}", instance, revision); //$NON-NLS-1$
+ }
+
+ // Handle containment
+ instanceToRevisionContainment();
+
+ // Handle values
+ CDOPackageRegistry packageRegistry = cdoView().getSession().getPackageRegistry();
+ EClass eClass = revision.getEClass();
+ for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass))
+ {
+ instanceToRevisionFeature(feature, packageRegistry);
+ }
+ }
+
+ protected void instanceToRevisionContainment()
+ {
+ CDOResource resource = (CDOResource)getInstanceResource(instance);
+ revision.setResourceID(resource == null ? CDOID.NULL : resource.cdoID());
+
+ InternalEObject eContainer = getInstanceContainer(instance);
+ if (eContainer == null)
+ {
+ revision.setContainerID(CDOID.NULL);
+ revision.setContainingFeatureID(0);
+ }
+ else
+ {
+ CDOObject cdoContainer = FSMUtil.adapt(eContainer, view);
+ revision.setContainerID(cdoContainer);
+ revision.setContainingFeatureID(getInstanceContainerFeatureID(instance));
+ }
+ }
+
+ protected void instanceToRevisionFeature(EStructuralFeature feature, CDOPackageRegistry packageRegistry)
+ {
+ Object instanceValue = getInstanceValue(instance, feature, packageRegistry);
+ CDOObjectImpl.instanceToRevisionFeature(view, this, feature, instanceValue);
+ }
+
+ protected void revisionToInstance()
+ {
+
+ if (underConstruction)
+ {
+ // Return if revisionToInstance was called before to avoid doubled calls
+ return;
+ }
+
+ underConstruction = true;
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Transfering revision to instance: {0} --> {1}", revision, instance); //$NON-NLS-1$
+ }
+
+ boolean deliver = instance.eDeliver();
+ if (deliver)
+ {
+ instance.eSetDeliver(false);
+ }
+
+ Counter counter = recursionCounter.get();
+
+ try
+ {
+ registerWrapper(this);
+ counter.increment();
+ view.registerObject(this);
+
+ revisionToInstanceContainer();
+
+ for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(revision.getEClass()))
+ {
+ revisionToInstanceFeature(feature);
+ }
+
+ revisionToInstanceResource();
+ }
+ catch (RuntimeException ex)
+ {
+ OM.LOG.error(ex);
+ throw ex;
+ }
+ catch (Exception ex)
+ {
+ OM.LOG.error(ex);
+ throw new CDOException(ex);
+ }
+ finally
+ {
+ if (deliver)
+ {
+ instance.eSetDeliver(true);
+ }
+
+ counter.decrement();
+ unregisterWrapper(this);
+ underConstruction = false;
+ }
+ }
+
+ /**
+ * @since 4.0
+ */
+ protected void revisionToInstanceContainer()
+ {
+ CDOPermission permission = revision.getPermission();
+ if (permission != CDOPermission.WRITE)
+ {
+ revision.setPermission(CDOPermission.WRITE);
+ }
+
+ try
+ {
+ Object containerID = revision.getContainerID();
+ InternalEObject container = getEObjectFromPotentialID(view, null, containerID);
+ EObject oldContainer = instance.eContainer();
+ if (oldContainer != container)
+ {
+ setInstanceContainer(container, revision.getContainingFeatureID());
+ }
+ }
+ finally
+ {
+ if (permission != CDOPermission.WRITE)
+ {
+ revision.setPermission(permission);
+ }
+ }
+ }
+
+ /**
+ * @since 4.0
+ */
+ protected void revisionToInstanceResource()
+ {
+ if (revision != null)
+ {
+ CDOID resourceID = revision.getResourceID();
+ InternalEObject resource = getEObjectFromPotentialID(view, null, resourceID);
+ setInstanceResource((Resource.Internal)resource);
+ if (resource != null)
+ {
+ view.registerObject((InternalCDOObject)resource);
+ }
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ protected void revisionToInstanceFeature(EStructuralFeature feature)
+ {
+ if (feature.isUnsettable() && !view.getStore().isSet(this, feature))
+ {
+ // Clarify if this is sufficient for bidirectional references
+ instance.eUnset(feature);
+ return;
+ }
+
+ if (feature.isMany())
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("State of Object (" + this + "/" + instance + ") is : " + state); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ if (state == CDOState.CLEAN || state == CDOState.PROXY || state == CDOState.NEW || state == CDOState.DIRTY)
+ {
+ int size = revision.size(feature);
+
+ @SuppressWarnings("unchecked")
+ InternalEList<Object> list = (InternalEList<Object>)instance.eGet(feature);
+
+ clearEList(list);
+ for (int i = 0; i < size; i++)
+ {
+ Object object = getValueFromRevision(feature, i);
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Adding " + object + " to feature " + feature + "in instance " + instance); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ list.basicAdd(object, null);
+ }
+ }
+ }
+ else
+ {
+ // !feature.isMany()
+ Object object = getValueFromRevision(feature, 0);
+ if (feature instanceof EAttribute)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting attribute value " + object + " to feature " + feature + " in instance " + instance); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ // Just fake it for the store :(
+ if (feature.isUnsettable() && object.equals(CDORevisionData.NIL))
+ {
+ eSet(feature, null);
+ }
+ else
+ {
+ eSet(feature, object);
+ }
+ }
+ else
+ {
+ // EReferences
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Adding object " + object + " to feature " + feature + " in instance " + instance); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ int featureID = instance.eClass().getFeatureID(feature);
+ Class<? extends Object> baseClass = object == null ? null : object.getClass();
+ EStructuralFeature.Internal internalFeature = (EStructuralFeature.Internal)feature;
+ EReference oppositeReference = internalFeature.getEOpposite();
+
+ if (oppositeReference != null)
+ {
+ if (object != null)
+ {
+ // If you have a containment reference but the container is not set, but the object is attached to a
+ // resource
+ // do not set the feature to null. Otherwise the object will be removed from the container which is the
+ // resource instead of the original container. As a result the object will be detached. See
+ // MapTest.testEObjectToEObjectValueContainedMap for more information
+ if (object != instance.eContainer())
+ {
+ instance.eInverseAdd((InternalEObject)object, featureID, baseClass, null);
+ }
+
+ if (!EMFUtil.isPersistent(oppositeReference))
+ {
+ adjustTransientOppositeReference(instance, (InternalEObject)object, oppositeReference);
+ }
+ }
+ }
+ else
+ {
+ if (object != CDORevisionData.NIL)
+ {
+ EReference reference = (EReference)feature;
+ if (reference.isContainment())
+ {
+ if (object != null)
+ {
+ // Calling eSet it not the optimal approach, but currently there is no other way to set the value here.
+ // To avoid attaching already processed (clean) objects a check was introduced to
+ // CDOResourceImpl.attached(EObject).
+ // If we find a way to avoid the call of eSet and if we are able to only set the feature value directly
+ // this check can be removed from CDOResourceImpl. See also Bug 352204.
+ instance.eSet(feature, object);
+ }
+ else
+ {
+ instance.eSet(feature, null);
+ }
+ }
+ else
+ {
+ instance.eSet(feature, object);
+ }
+ }
+ else
+ {
+ instance.eSet(feature, null);
+ }
+ }
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Added object " + object + " to feature " + feature + " in instance " + instance); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+ }
+ }
+
+ /**
+ * This method retrieves the value from the feature at the given index. It retrieves the value either from the views's
+ * store or the internal pre-registration Map.
+ *
+ * @param feature
+ * the feature to retrieve the value from
+ * @param index
+ * the given index of the object in the feature
+ * @return the value from the feature at the given index
+ */
+ private Object getValueFromRevision(EStructuralFeature feature, int index)
+ {
+ Object object = revision.get(feature, index);
+ if (object == null)
+ {
+ return null;
+ }
+
+ if (object instanceof CDOElementProxy)
+ {
+ // Resolve proxy
+ CDOElementProxy proxy = (CDOElementProxy)object;
+ object = view.getSession().resolveElementProxy(revision, feature, index, proxy.getIndex());
+ }
+
+ if (object instanceof CDOLegacyWrapper)
+ {
+ return ((CDOLegacyWrapper)object).cdoInternalInstance();
+ }
+
+ CDOType type = CDOModelUtil.getType(feature.getEType());
+ object = view.getStore().convertToEMF(instance, revision, feature, index, object);
+
+ if (type == CDOType.OBJECT)
+ {
+ if (object instanceof CDOID)
+ {
+ CDOID id = (CDOID)object;
+ if (id.isNull())
+ {
+ return null;
+ }
+
+ object = getRegisteredWrapper(id);
+ if (object != null)
+ {
+ return ((CDOLegacyWrapper)object).cdoInternalInstance();
+ }
+
+ if (id.isExternal())
+ {
+ object = view.getResourceSet().getEObject(URI.createURI(id.toURIFragment()), true);
+ }
+ else
+ {
+ object = view.getObject(id);
+ }
+
+ if (object instanceof CDOObjectWrapper)
+ {
+ return ((CDOObjectWrapper)object).cdoInternalInstance();
+ }
+ }
+ }
+
+ return object;
+ }
+
+ protected Resource.Internal getInstanceResource(InternalEObject instance)
+ {
+ return instance.eDirectResource();
+ }
+
+ protected InternalEObject getInstanceContainer(InternalEObject instance)
+ {
+ return instance.eInternalContainer();
+ }
+
+ protected int getInstanceContainerFeatureID(InternalEObject instance)
+ {
+ return instance.eContainerFeatureID();
+ }
+
+ protected Object getInstanceValue(InternalEObject instance, EStructuralFeature feature,
+ CDOPackageRegistry packageRegistry)
+ {
+ return instance.eGet(feature);
+ }
+
+ protected void setInstanceResource(Resource.Internal resource)
+ {
+ Method method = ReflectUtil.getMethod(instance.getClass(), "eSetDirectResource", Resource.Internal.class); //$NON-NLS-1$
+ ReflectUtil.invokeMethod(method, instance, resource);
+ }
+
+ protected void setInstanceContainer(InternalEObject container, int containerFeatureID)
+ {
+ Method method = ReflectUtil.getMethod(instance.getClass(), "eBasicSetContainer", InternalEObject.class, int.class); //$NON-NLS-1$
+ ReflectUtil.invokeMethod(method, instance, container, containerFeatureID);
+ }
+
+ protected void setInstanceValue(InternalEObject instance, EStructuralFeature feature, Object value)
+ {
+ instance.eSet(feature, value);
+ }
+
+ /**
+ * @param feature
+ * in case that a proxy has to be created the feature that will determine the interface type of the proxy and
+ * that will be used later to resolve the proxy. <code>null</code> indicates that proxy creation will be
+ * avoided!
+ */
+ protected InternalEObject getEObjectFromPotentialID(InternalCDOView view, EStructuralFeature feature,
+ Object potentialID)
+ {
+ CDOLegacyWrapper wrapper;
+ if (potentialID instanceof CDOID && (wrapper = getRegisteredWrapper((CDOID)potentialID)) != null)
+ {
+ potentialID = wrapper.instance;
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Getting Object (" + potentialID + ") from localThread instead of the view"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ else
+ {
+ if (potentialID instanceof CDOID)
+ {
+ CDOID id = (CDOID)potentialID;
+ if (id.isNull())
+ {
+ return null;
+ }
+
+ if (id.isExternal())
+ {
+ URI uri = URI.createURI(id.toURIFragment());
+ InternalEObject eObject = (InternalEObject)view.getResourceSet().getEObject(uri, true);
+ return eObject;
+ }
+
+ boolean loadOnDemand = feature == null;
+ potentialID = view.getObject(id, loadOnDemand);
+ if (potentialID == null && !loadOnDemand)
+ {
+ return createProxy(view, feature, id);
+ }
+ }
+
+ if (potentialID instanceof InternalCDOObject)
+ {
+ return ((InternalCDOObject)potentialID).cdoInternalInstance();
+ }
+ }
+
+ return (InternalEObject)potentialID;
+ }
+
+ /**
+ * Creates and returns a <em>proxy</em> object. The usage of a proxy object is strongly limited. The only guarantee
+ * that can be made is that the following methods are callable and will behave in the expected way:
+ * <ul>
+ * <li>{@link CDOObject#cdoID()} will return the {@link CDOID} of the target object
+ * <li>{@link CDOObject#cdoState()} will return {@link CDOState#PROXY PROXY}
+ * <li>{@link InternalEObject#eIsProxy()} will return <code>true</code>
+ * <li>{@link InternalEObject#eProxyURI()} will return the EMF proxy URI of the target object
+ * </ul>
+ * Calling any other method on the proxy object will result in an {@link UnsupportedOperationException} being thrown
+ * at runtime. Note also that the proxy object might even not be cast to the concrete type of the target object. The
+ * proxy can only guaranteed to be of <em>any</em> concrete subtype of the declared type of the given feature.
+ * <p>
+ * TODO {@link InternalEObject#eResolveProxy(InternalEObject)}
+ */
+ protected InternalEObject createProxy(InternalCDOView view, EStructuralFeature feature, CDOID id)
+ {
+ EClassifier eType = feature.getEType();
+ Class<?> instanceClass = eType.getInstanceClass();
+
+ Class<?>[] interfaces = { instanceClass, InternalEObject.class, LegacyProxy.class };
+ ClassLoader classLoader = CDOLegacyWrapper.class.getClassLoader();
+ LegacyProxyInvocationHandler handler = new LegacyProxyInvocationHandler(this, id);
+ return (InternalEObject)Proxy.newProxyInstance(classLoader, interfaces, handler);
+ }
+
+ protected void clearEList(InternalEList<?> list)
+ {
+ for (int i = list.size() - 1; i >= 0; --i)
+ {
+ Object obj = list.get(i);
+ list.basicRemove(obj, null);
+ }
+ }
+
+ /**
+ * TODO Consider using only EMF concepts for resolving proxies!
+ */
+ protected void resolveAllProxies()
+ {
+ CDOPackageRegistry packageRegistry = cdoView().getSession().getPackageRegistry();
+ EClass eClass = revision.getEClass();
+ for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass))
+ {
+ if (feature instanceof EReference)
+ {
+ resolveProxies(feature, packageRegistry);
+ }
+ }
+ }
+
+ /**
+ * IMPORTANT: Compile errors in this method might indicate an old version of EMF. Legacy support is only enabled for
+ * EMF with fixed bug #247130. These compile errors do not affect native models!
+ */
+ protected void resolveProxies(EStructuralFeature feature, CDOPackageRegistry packageRegistry)
+ {
+ Object value = getInstanceValue(instance, feature, packageRegistry);
+ if (value != null)
+ {
+ if (feature.isMany())
+ {
+ @SuppressWarnings("unchecked")
+ InternalEList<Object> list = (InternalEList<Object>)value;
+ int size = list.size();
+
+ boolean deliver = instance.eDeliver();
+ if (deliver)
+ {
+ instance.eSetDeliver(false);
+ }
+
+ for (int i = 0; i < size; i++)
+ {
+ Object element = list.get(i);
+ if (element instanceof LegacyProxy)
+ {
+ CDOID id = ((LegacyProxy)element).getID();
+ InternalCDOObject resolved = (InternalCDOObject)view.getObject(id);
+ InternalEObject instance = resolved.cdoInternalInstance();
+
+ // TODO LEGACY
+ // // TODO Is InternalEList.basicSet() needed???
+ // if (list instanceof
+ // org.eclipse.emf.ecore.util.DelegatingInternalEList)
+ // {
+ // list =
+ // ((org.eclipse.emf.ecore.util.DelegatingInternalEList)list).getDelegateInternalEList();
+ // }
+
+ // if (list instanceof NotifyingListImpl<?>)
+ // {
+ // ((NotifyingListImpl<Object>)list).basicSet(i, instance, null);
+ // }
+ // else
+ // {
+ list.set(i, instance);
+ // }
+ }
+ }
+
+ if (deliver)
+ {
+ instance.eSetDeliver(true);
+ }
+ }
+ else
+ {
+ if (value instanceof LegacyProxy)
+ {
+ CDOID id = ((LegacyProxy)value).getID();
+ InternalCDOObject resolved = (InternalCDOObject)view.getObject(id);
+ InternalEObject instance = resolved.cdoInternalInstance();
+ setInstanceValue(instance, feature, instance);
+ }
+ }
+ }
+ }
+
+ protected void adjustEProxy()
+ {
+ // Setting eProxyURI is necessary to prevent content adapters from
+ // loading the whole content tree.
+ // TODO Does not have the desired effect ;-( see CDOEditor.createModel()
+ if (state == CDOState.PROXY)
+ {
+ if (!instance.eIsProxy())
+ {
+ URI uri = URI.createURI(CDOProtocolConstants.PROTOCOL_NAME + ":proxy#" + id); //$NON-NLS-1$
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting proxyURI {0} for {1}", uri, instance); //$NON-NLS-1$
+ }
+
+ instance.eSetProxyURI(uri);
+ }
+ }
+ else
+ {
+ if (instance.eIsProxy())
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Unsetting proxyURI for {0}", instance); //$NON-NLS-1$
+ }
+
+ instance.eSetProxyURI(null);
+ }
+ }
+ }
+
+ @Override
+ public synchronized EList<Adapter> eAdapters()
+ {
+ EList<Adapter> adapters = instance.eAdapters();
+ for (Adapter adapter : adapters)
+ {
+ if (!FSMUtil.isTransient(this) && !(adapter instanceof CDOLegacyWrapper))
+ {
+ cdoView().handleAddAdapter(this, adapter);
+ }
+ }
+
+ return adapters;
+ }
+
+ public static boolean isLegacyProxy(Object object)
+ {
+ return object instanceof LegacyProxy;
+ }
+
+ protected static int getEFlagMask(Class<?> instanceClass, String flagName)
+ {
+ Field field = ReflectUtil.getField(instanceClass, flagName);
+ if (!field.isAccessible())
+ {
+ field.setAccessible(true);
+ }
+
+ try
+ {
+ return (Integer)field.get(null);
+ }
+ catch (IllegalAccessException ex)
+ {
+ throw WrappedException.wrap(ex);
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ protected static CDOLegacyWrapper getRegisteredWrapper(CDOID id)
+ {
+ return wrapperRegistry.get().get(id);
+ }
+
+ /**
+ * Adds an object to the pre-registered objects list which hold all created objects even if they are not registered in
+ * the view
+ *
+ * @since 3.0
+ */
+ protected static void registerWrapper(CDOLegacyWrapper wrapper)
+ {
+ wrapperRegistry.get().put(wrapper.cdoID(), wrapper);
+ }
+
+ /**
+ * @since 3.0
+ */
+ protected static void unregisterWrapper(CDOLegacyWrapper wrapper)
+ {
+ wrapperRegistry.get().remove(wrapper.cdoID());
+ }
+
+ /**
+ * @since 3.0
+ */
+ protected static boolean isRegisteredWrapper(CDOLegacyWrapper wrapper)
+ {
+ return wrapperRegistry.get().containsKey(wrapper.cdoID());
+ }
+
+ // TODO: Remove this method if it is ensured that ist is not needed anymore
+ // private void adjustOppositeReference(InternalCDOObject cdoObject, EObject oppositeObject, EReference
+ // oppositeReference)
+ // {
+ // if (oppositeObject != null)
+ // {
+ // InternalCDOObject oppositeCDOObject = (InternalCDOObject)CDOUtil.getCDOObject(oppositeObject);
+ //
+ // if (!FSMUtil.isTransient(oppositeCDOObject) && !EMFUtil.isPersistent(oppositeReference))
+ // {
+ // adjustPersistentOppositeReference(cdoObject, oppositeObject, oppositeReference);
+ // }
+ // else
+ // {
+ // if (oppositeReference.isResolveProxies())
+ // {
+ // adjustTransientOppositeReference(instance, (InternalEObject)oppositeObject, oppositeReference);
+ // }
+ // }
+ // }
+ // }
+
+ private void adjustPersistentOppositeReference(InternalCDOObject cdoObject, EObject oppositeObject,
+ EReference oppositeReference)
+ {
+ InternalCDOObject oppositeCDOObject = (InternalCDOObject)CDOUtil.getCDOObject(oppositeObject);
+ if (oppositeCDOObject != null)
+ {
+ InternalCDOView view = oppositeCDOObject.cdoView();
+ if (view != null)
+ {
+ CDOStore store = view.getStore();
+ if (store != null)
+ {
+ if (oppositeReference.isMany())
+ {
+ EObject eObject = oppositeCDOObject.cdoInternalInstance();
+
+ @SuppressWarnings("unchecked")
+ EList<Object> list = (EList<Object>)eObject.eGet(oppositeReference);
+ int index = list.indexOf(instance);
+
+ if (!store.isEmpty(oppositeCDOObject, oppositeReference) && index != EStore.NO_INDEX)
+ {
+ store.set(oppositeCDOObject, oppositeReference, index, cdoObject);
+ }
+ }
+ else
+ {
+ store.set(oppositeCDOObject, oppositeReference, 0, cdoObject);
+ }
+ }
+ }
+ }
+ }
+
+ private void adjustTransientOppositeReference(InternalEObject instance, InternalEObject object,
+ EReference oppositeReference)
+ {
+ boolean wasDeliver = object.eDeliver(); // Disable notifications
+ if (wasDeliver)
+ {
+ object.eSetDeliver(false);
+ }
+
+ try
+ {
+ if (oppositeReference.isMany())
+ {
+ @SuppressWarnings("unchecked")
+ InternalEList<Object> list = (InternalEList<Object>)object.eGet(oppositeReference);
+ list.basicAdd(instance, null);
+ }
+ else
+ {
+ if (object.eGet(oppositeReference) != instance)
+ {
+ object.eInverseAdd(instance, oppositeReference.getFeatureID(), ((EObject)instance).getClass(), null);
+ }
+ }
+ }
+ finally
+ {
+ if (wasDeliver)
+ {
+ object.eSetDeliver(true);
+ }
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static interface LegacyProxy
+ {
+ public CDOID getID();
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class LegacyProxyInvocationHandler implements InvocationHandler, LegacyProxy
+ {
+ private static final Method getIDMethod = ReflectUtil.getMethod(LegacyProxy.class, "getID"); //$NON-NLS-1$
+
+ private static final Method eIsProxyMethod = ReflectUtil.getMethod(EObject.class, "eIsProxy"); //$NON-NLS-1$
+
+ private static final Method eProxyURIMethod = ReflectUtil.getMethod(InternalEObject.class, "eProxyURI"); //$NON-NLS-1$
+
+ private CDOLegacyWrapper wrapper;
+
+ private CDOID id;
+
+ public LegacyProxyInvocationHandler(CDOLegacyWrapper wrapper, CDOID id)
+ {
+ this.wrapper = wrapper;
+ this.id = id;
+ }
+
+ public CDOID getID()
+ {
+ return id;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+ {
+ if (method.equals(getIDMethod))
+ {
+ return id;
+ }
+
+ if (method.equals(eIsProxyMethod))
+ {
+ return true;
+ }
+
+ if (method.equals(eProxyURIMethod))
+ {
+ // Use container's resource because it's guaranteed to be in the same CDOView as the resource of the target!
+ Resource resource = wrapper.eResource();
+
+ // TODO Consider using a "fake" Resource implementation. See Resource.getEObject(...)
+ return resource.getURI().appendFragment(id.toURIFragment());
+ }
+
+ // A client must have invoked the proxy while being told not to do so!
+ throw new UnsupportedOperationException(method.getName());
+ }
+ }
+
+ /**
+ * @author Martin Fluegge
+ */
+ private static final class Counter
+ {
+ private int value;
+
+ public Counter()
+ {
+ }
+
+ public void increment()
+ {
+ ++value;
+ }
+
+ public int decrement()
+ {
+ return --value;
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java
index ffb614135b..1599b2ae86 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java
@@ -1,1032 +1,1055 @@
-/*
- * Copyright (c) 2004 - 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
- * Simon McDuff - maintenance
- */
-package org.eclipse.emf.internal.cdo.view;
-
-import org.eclipse.emf.cdo.CDOObject;
-import org.eclipse.emf.cdo.CDOState;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDTemp;
-import org.eclipse.emf.cdo.common.model.EMFUtil;
-import org.eclipse.emf.cdo.common.revision.CDORevisable;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionFactory;
-import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
-import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
-import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
-import org.eclipse.emf.cdo.common.util.PartialCollectionLoadingNotSupportedException;
-import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
-import org.eclipse.emf.cdo.transaction.CDOTransaction;
-import org.eclipse.emf.cdo.view.CDOInvalidationPolicy;
-import org.eclipse.emf.cdo.view.CDOView;
-
-import org.eclipse.emf.internal.cdo.CDOObjectImpl;
-import org.eclipse.emf.internal.cdo.bundle.OM;
-import org.eclipse.emf.internal.cdo.object.CDONotificationBuilder;
-
-import org.eclipse.net4j.util.collection.Pair;
-import org.eclipse.net4j.util.fsm.FiniteStateMachine;
-import org.eclipse.net4j.util.fsm.ITransition;
-import org.eclipse.net4j.util.om.trace.ContextTracer;
-
-import org.eclipse.emf.common.notify.NotificationChain;
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EPackage;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.InternalEObject;
-import org.eclipse.emf.ecore.impl.EStoreEObjectImpl;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.spi.cdo.CDOSessionProtocol.CommitTransactionResult;
-import org.eclipse.emf.spi.cdo.FSMUtil;
-import org.eclipse.emf.spi.cdo.InternalCDOObject;
-import org.eclipse.emf.spi.cdo.InternalCDOSavepoint;
-import org.eclipse.emf.spi.cdo.InternalCDOSession;
-import org.eclipse.emf.spi.cdo.InternalCDOTransaction;
-import org.eclipse.emf.spi.cdo.InternalCDOView;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Eike Stepper
- */
-public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent, InternalCDOObject>
-{
- // @Singleton
- public static final CDOStateMachine INSTANCE = new CDOStateMachine();
-
- private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_STATEMACHINE, CDOStateMachine.class);
-
- private InternalCDOObject lastTracedObject;
-
- private CDOState lastTracedState;
-
- private CDOEvent lastTracedEvent;
-
- @SuppressWarnings("unchecked")
- private CDOStateMachine()
- {
- super(CDOState.class, CDOEvent.class);
-
- init(CDOState.TRANSIENT, CDOEvent.PREPARE, new PrepareTransition());
- init(CDOState.TRANSIENT, CDOEvent.ATTACH, FAIL);
- init(CDOState.TRANSIENT, CDOEvent.DETACH, IGNORE);
- init(CDOState.TRANSIENT, CDOEvent.REATTACH, new ReattachTransition());
- init(CDOState.TRANSIENT, CDOEvent.READ, IGNORE);
- init(CDOState.TRANSIENT, CDOEvent.WRITE, IGNORE);
- init(CDOState.TRANSIENT, CDOEvent.INVALIDATE, IGNORE);
- init(CDOState.TRANSIENT, CDOEvent.DETACH_REMOTE, IGNORE);
- init(CDOState.TRANSIENT, CDOEvent.COMMIT, FAIL);
- init(CDOState.TRANSIENT, CDOEvent.ROLLBACK, FAIL);
-
- init(CDOState.PREPARED, CDOEvent.PREPARE, FAIL);
- init(CDOState.PREPARED, CDOEvent.ATTACH, new AttachTransition());
- init(CDOState.PREPARED, CDOEvent.DETACH, FAIL);
- init(CDOState.PREPARED, CDOEvent.REATTACH, FAIL);
- init(CDOState.PREPARED, CDOEvent.READ, IGNORE);
- init(CDOState.PREPARED, CDOEvent.WRITE, FAIL);
- init(CDOState.PREPARED, CDOEvent.INVALIDATE, FAIL);
- init(CDOState.PREPARED, CDOEvent.DETACH_REMOTE, FAIL);
- init(CDOState.PREPARED, CDOEvent.COMMIT, FAIL);
- init(CDOState.PREPARED, CDOEvent.ROLLBACK, FAIL);
-
- init(CDOState.NEW, CDOEvent.PREPARE, FAIL);
- init(CDOState.NEW, CDOEvent.ATTACH, FAIL);
- init(CDOState.NEW, CDOEvent.DETACH, new DetachTransition());
- init(CDOState.NEW, CDOEvent.REATTACH, FAIL);
- init(CDOState.NEW, CDOEvent.READ, IGNORE);
- init(CDOState.NEW, CDOEvent.WRITE, new WriteNewTransition());
- init(CDOState.NEW, CDOEvent.INVALIDATE, FAIL);
- init(CDOState.NEW, CDOEvent.DETACH_REMOTE, FAIL);
- init(CDOState.NEW, CDOEvent.COMMIT, new CommitTransition(false));
- init(CDOState.NEW, CDOEvent.ROLLBACK, FAIL);
-
- init(CDOState.CLEAN, CDOEvent.PREPARE, FAIL);
- init(CDOState.CLEAN, CDOEvent.ATTACH, FAIL);
- init(CDOState.CLEAN, CDOEvent.DETACH, new DetachTransition());
- init(CDOState.CLEAN, CDOEvent.REATTACH, FAIL);
- init(CDOState.CLEAN, CDOEvent.READ, IGNORE);
- init(CDOState.CLEAN, CDOEvent.WRITE, new WriteTransition());
- init(CDOState.CLEAN, CDOEvent.INVALIDATE, new InvalidateTransition());
- init(CDOState.CLEAN, CDOEvent.DETACH_REMOTE, DetachRemoteTransition.INSTANCE);
- init(CDOState.CLEAN, CDOEvent.COMMIT, FAIL);
- init(CDOState.CLEAN, CDOEvent.ROLLBACK, FAIL);
-
- init(CDOState.DIRTY, CDOEvent.PREPARE, FAIL);
- init(CDOState.DIRTY, CDOEvent.ATTACH, FAIL);
- init(CDOState.DIRTY, CDOEvent.DETACH, new DetachTransition());
- init(CDOState.DIRTY, CDOEvent.REATTACH, FAIL);
- init(CDOState.DIRTY, CDOEvent.READ, IGNORE);
- init(CDOState.DIRTY, CDOEvent.WRITE, new RewriteTransition());
- init(CDOState.DIRTY, CDOEvent.INVALIDATE, new ConflictTransition());
- init(CDOState.DIRTY, CDOEvent.DETACH_REMOTE, new InvalidConflictTransition());
- init(CDOState.DIRTY, CDOEvent.COMMIT, new CommitTransition(true));
- init(CDOState.DIRTY, CDOEvent.ROLLBACK, new RollbackTransition());
-
- init(CDOState.PROXY, CDOEvent.PREPARE, FAIL);
- init(CDOState.PROXY, CDOEvent.ATTACH, FAIL);
- init(CDOState.PROXY, CDOEvent.DETACH, new DetachTransition());
- init(CDOState.PROXY, CDOEvent.REATTACH, FAIL);
- init(CDOState.PROXY, CDOEvent.READ, new LoadTransition(false));
- init(CDOState.PROXY, CDOEvent.WRITE, new LoadTransition(true));
- init(CDOState.PROXY, CDOEvent.INVALIDATE, IGNORE);
- init(CDOState.PROXY, CDOEvent.DETACH_REMOTE, DetachRemoteTransition.INSTANCE);
- init(CDOState.PROXY, CDOEvent.COMMIT, FAIL);
- init(CDOState.PROXY, CDOEvent.ROLLBACK, FAIL);
-
- init(CDOState.CONFLICT, CDOEvent.PREPARE, FAIL);
- init(CDOState.CONFLICT, CDOEvent.ATTACH, IGNORE);
- init(CDOState.CONFLICT, CDOEvent.DETACH, new DetachTransition());
- init(CDOState.CONFLICT, CDOEvent.REATTACH, FAIL);
- init(CDOState.CONFLICT, CDOEvent.READ, IGNORE);
- init(CDOState.CONFLICT, CDOEvent.WRITE, new RewriteTransition());
- init(CDOState.CONFLICT, CDOEvent.INVALIDATE, IGNORE);
- init(CDOState.CONFLICT, CDOEvent.DETACH_REMOTE, IGNORE);
- init(CDOState.CONFLICT, CDOEvent.COMMIT, IGNORE);
- init(CDOState.CONFLICT, CDOEvent.ROLLBACK, new RollbackTransition());
-
- init(CDOState.INVALID, CDOEvent.PREPARE, InvalidTransition.INSTANCE);
- init(CDOState.INVALID, CDOEvent.ATTACH, InvalidTransition.INSTANCE);
- init(CDOState.INVALID, CDOEvent.DETACH, InvalidTransition.INSTANCE);
- init(CDOState.INVALID, CDOEvent.REATTACH, FAIL);
- init(CDOState.INVALID, CDOEvent.READ, InvalidTransition.INSTANCE);
- init(CDOState.INVALID, CDOEvent.WRITE, InvalidTransition.INSTANCE);
- init(CDOState.INVALID, CDOEvent.INVALIDATE, IGNORE); // TODO Handle changeViewTarget!!!
- init(CDOState.INVALID, CDOEvent.DETACH_REMOTE, IGNORE);
- init(CDOState.INVALID, CDOEvent.COMMIT, InvalidTransition.INSTANCE);
- init(CDOState.INVALID, CDOEvent.ROLLBACK, InvalidTransition.INSTANCE);
-
- init(CDOState.INVALID_CONFLICT, CDOEvent.PREPARE, InvalidTransition.INSTANCE);
- init(CDOState.INVALID_CONFLICT, CDOEvent.ATTACH, InvalidTransition.INSTANCE);
- init(CDOState.INVALID_CONFLICT, CDOEvent.DETACH, InvalidTransition.INSTANCE);
- init(CDOState.INVALID_CONFLICT, CDOEvent.REATTACH, FAIL);
- init(CDOState.INVALID_CONFLICT, CDOEvent.READ, IGNORE);
- init(CDOState.INVALID_CONFLICT, CDOEvent.WRITE, IGNORE);
- init(CDOState.INVALID_CONFLICT, CDOEvent.INVALIDATE, IGNORE);
- init(CDOState.INVALID_CONFLICT, CDOEvent.DETACH_REMOTE, IGNORE);
- init(CDOState.INVALID_CONFLICT, CDOEvent.COMMIT, InvalidTransition.INSTANCE);
- init(CDOState.INVALID_CONFLICT, CDOEvent.ROLLBACK, DetachRemoteTransition.INSTANCE);
- }
-
- /**
- * The object is already attached in EMF world. It contains all the information needed to know where it will be
- * connected.
- *
- * @since 2.0
- */
- public void attach(InternalCDOObject object, InternalCDOTransaction transaction)
- {
- synchronized (transaction)
- {
- List<InternalCDOObject> contents = new ArrayList<InternalCDOObject>();
- prepare(object, new Pair<InternalCDOTransaction, List<InternalCDOObject>>(transaction, contents));
-
- attachOrReattach(object, transaction);
- for (InternalCDOObject content : contents)
- {
- attachOrReattach(content, transaction);
- }
- }
- }
-
- private void attachOrReattach(InternalCDOObject object, InternalCDOTransaction transaction)
- {
- // Bug 283985 (Re-attachment):
- // If the object going through a prepareTransition is present in cleanRevisions,
- // then it was detached earlier, and so we can infer that it is being re-attached
- if (transaction.getCleanRevisions().containsKey(object))
- {
- reattachObject(object, transaction);
- }
- else
- {
- attachObject(object);
- }
- }
-
- /**
- * Phase 1: TRANSIENT --> PREPARED
- */
- private void prepare(InternalCDOObject object,
- Pair<InternalCDOTransaction, List<InternalCDOObject>> transactionAndContents)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("PREPARE: {0} --> {1}", object, transactionAndContents.getElement1()); //$NON-NLS-1$
- }
-
- process(object, CDOEvent.PREPARE, transactionAndContents);
- }
-
- /**
- * Phase 2: PREPARED --> NEW
- */
- private void attachObject(InternalCDOObject object)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("ATTACH: {0}", object); //$NON-NLS-1$
- }
-
- process(object, CDOEvent.ATTACH, null);
- }
-
- private void reattachObject(InternalCDOObject object, InternalCDOTransaction transaction)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("REATTACH: {0}", object);
- }
-
- process(object, CDOEvent.REATTACH, transaction);
- }
-
- /**
- * @since 2.0
- */
- public void detach(InternalCDOObject object)
- {
- synchronized (getMonitor(object))
- {
- if (TRACER.isEnabled())
- {
- trace(object, CDOEvent.DETACH);
- }
-
- List<InternalCDOObject> objectsToDetach = new ArrayList<InternalCDOObject>();
- InternalCDOTransaction transaction = (InternalCDOTransaction)object.cdoView();
-
- // Accumulate objects that needs to be detached
- // If we have an error, we will keep the graph exactly like it was before.
- process(object, CDOEvent.DETACH, objectsToDetach);
-
- // postDetach requires the object to be TRANSIENT
- for (InternalCDOObject content : objectsToDetach)
- {
- CDOState oldState = content.cdoInternalSetState(CDOState.TRANSIENT);
- content.cdoInternalPostDetach(false);
- content.cdoInternalSetState(oldState);
- }
-
- // detachObject needs to know the state before we change the object to TRANSIENT
- for (InternalCDOObject content : objectsToDetach)
- {
- transaction.detachObject(content);
- content.cdoInternalSetState(CDOState.TRANSIENT);
-
- content.cdoInternalSetView(null);
- content.cdoInternalSetID(null);
- content.cdoInternalSetRevision(null);
- }
- }
- }
-
- /**
- * @since 2.0
- */
- public InternalCDORevision read(InternalCDOObject object)
- {
- synchronized (getMonitor(object))
- {
- if (TRACER.isEnabled())
- {
- trace(object, CDOEvent.READ);
- }
-
- process(object, CDOEvent.READ, null);
-
- return object.cdoRevision();
- }
- }
-
- /**
- * @since 2.0
- */
- public InternalCDORevision readNoLoad(InternalCDOObject object)
- {
- synchronized (getMonitor(object))
- {
- switch (object.cdoState())
- {
- case TRANSIENT:
- case PREPARED:
- case NEW:
- case CONFLICT:
- case INVALID_CONFLICT:
- case INVALID:
- case PROXY:
- return null;
- }
-
- return object.cdoRevision();
- }
- }
-
- /**
- * @since 2.0
- */
- public void write(InternalCDOObject object)
- {
- write(object, null);
- }
-
- /**
- * @since 2.0
- */
- public void write(InternalCDOObject object, CDOFeatureDelta featureDelta)
- {
- synchronized (getMonitor(object))
- {
- writeWithoutViewLock(object, featureDelta);
- }
- }
-
- private void writeWithoutViewLock(InternalCDOObject object, CDOFeatureDelta featureDelta)
- {
- if (TRACER.isEnabled())
- {
- trace(object, CDOEvent.WRITE);
- }
-
- process(object, CDOEvent.WRITE, featureDelta);
- }
-
- /**
- * @since 2.0
- */
- public void reload(InternalCDOObject... objects)
- {
- if (objects == null || objects.length == 0)
- {
- return;
- }
-
- synchronized (getMonitor(objects[0]))
- {
- for (InternalCDOObject object : objects)
- {
- CDOState state = object.cdoState();
- if (state == CDOState.CLEAN || state == CDOState.PROXY)
- {
- changeState(object, CDOState.PROXY);
- object.cdoInternalSetRevision(null);
- read(object);
- }
- }
- }
- }
-
- /**
- * @since 3.0
- */
- public void invalidate(InternalCDOObject object, CDORevisionKey key, long lastUpdateTime)
- {
- synchronized (getMonitor(object))
- {
- if (TRACER.isEnabled())
- {
- trace(object, CDOEvent.INVALIDATE);
- }
-
- process(object, CDOEvent.INVALIDATE, new Pair<CDORevisionKey, Long>(key, lastUpdateTime));
- }
- }
-
- /**
- * @since 2.0
- */
- public void detachRemote(InternalCDOObject object)
- {
- synchronized (getMonitor(object))
- {
- if (TRACER.isEnabled())
- {
- trace(object, CDOEvent.DETACH_REMOTE);
- }
-
- process(object, CDOEvent.DETACH_REMOTE, null);
- }
- }
-
- /**
- * @since 2.0
- */
- public void commit(InternalCDOObject object, CommitTransactionResult result)
- {
- synchronized (getMonitor(object))
- {
- if (TRACER.isEnabled())
- {
- trace(object, CDOEvent.COMMIT);
- }
-
- process(object, CDOEvent.COMMIT, result);
- }
- }
-
- /**
- * @since 2.0
- */
- public void rollback(InternalCDOObject object)
- {
- synchronized (getMonitor(object))
- {
- if (TRACER.isEnabled())
- {
- trace(object, CDOEvent.ROLLBACK);
- }
-
- process(object, CDOEvent.ROLLBACK, null);
- object.cdoInternalPostRollback();
- }
- }
-
- @Override
- protected CDOState getState(InternalCDOObject object)
- {
- return object.cdoState();
- }
-
- @Override
- protected void setState(InternalCDOObject object, CDOState state)
- {
- object.cdoInternalSetState(state);
- }
-
- private Object getMonitor(InternalCDOObject object)
- {
- InternalCDOView view = object.cdoView();
- if (view != null)
- {
- return view;
- }
-
- // In TRANSIENT and PREPARED the object is not yet attached to a view
- return object;
- }
-
- /**
- * Removes clutter from the trace log
- */
- private void trace(InternalCDOObject object, CDOEvent event)
- {
- CDOState state = object.cdoState();
- if (lastTracedObject != object || lastTracedState != state || lastTracedEvent != event)
- {
- TRACER.format("{0}: {1}", event, object.getClass().getName()); //$NON-NLS-1$
- lastTracedObject = object;
- lastTracedState = state;
- lastTracedEvent = event;
- }
- }
-
- @SuppressWarnings("unused")
- private void testAttach(InternalCDOObject object)
- {
- process(object, CDOEvent.ATTACH, null);
- }
-
- /**
- * Prepares a tree of transient objects to be subsequently {@link AttachTransition attached} to a CDOView.
- * <p>
- * Execution is recursive and includes:
- * <ol>
- * <li>Assignment of a new {@link CDOIDTemp}
- * <li>Assignment of a new {@link CDORevision}
- * <li>Bidirectional association with the {@link CDOView}
- * <li>Registration with the {@link CDOTransaction}
- * <li>Changing state to {@link CDOState#PREPARED PREPARED}
- * </ol>
- *
- * @see AttachTransition
- * @author Eike Stepper
- */
- private final class PrepareTransition implements
- ITransition<CDOState, CDOEvent, InternalCDOObject, Pair<InternalCDOTransaction, List<InternalCDOObject>>>
- {
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event,
- Pair<InternalCDOTransaction, List<InternalCDOObject>> transactionAndContents)
- {
- InternalCDOTransaction transaction = transactionAndContents.getElement1();
- List<InternalCDOObject> contents = transactionAndContents.getElement2();
-
- // If the object going through a prepareTransition is present in cleanRevisions,
- // then it was detached earlier, and so we can infer that it is being re-attached
- boolean reattaching = transaction.getCleanRevisions().containsKey(object);
-
- if (!reattaching)
- {
- // Prepare object
- CDOID id = transaction.createIDForNewObject(object.cdoInternalInstance());
- object.cdoInternalSetID(id);
- object.cdoInternalSetView(transaction);
- changeState(object, CDOState.PREPARED);
-
- // Create new revision
- EClass eClass = object.eClass();
- InternalCDOSession session = transaction.getSession();
- checkPackageRegistrationProblems(session, eClass);
-
- CDORevisionFactory factory = session.getRevisionManager().getFactory();
- InternalCDORevision revision = (InternalCDORevision)factory.createRevision(eClass);
- revision.setID(id);
- revision.setBranchPoint(transaction.getBranch().getHead());
-
- object.cdoInternalSetRevision(revision);
-
- // Register object
- transaction.registerObject(object);
- }
-
- transaction.registerAttached(object, !reattaching);
-
- // Prepare content tree
- for (Iterator<InternalCDOObject> it = getProperContents(object, transaction); it.hasNext();)
- {
- InternalCDOObject content = it.next();
- contents.add(content);
- INSTANCE.process(content, CDOEvent.PREPARE, transactionAndContents);
- }
- }
-
- private void checkPackageRegistrationProblems(InternalCDOSession session, EClass eClass)
- {
- if (session.options().isGeneratedPackageEmulationEnabled())
- {
- // Check that there are no multiple EPackages with the same URI in system. Bug 335004
- String packageURI = eClass.getEPackage().getNsURI();
- Object packageObject = session.getPackageRegistry().get(packageURI);
- if (packageObject instanceof InternalCDOPackageInfo)
- {
- packageObject = ((InternalCDOPackageInfo)packageObject).getEPackage(false);
- }
-
- if (packageObject instanceof EPackage && packageObject != eClass.getEPackage())
- {
- throw new IllegalStateException(MessageFormat.format(
- "Global EPackage {0} for EClass {1} is different from EPackage found in CDOPackageRegistry", packageURI,
- eClass));
- }
- }
- }
-
- private Iterator<InternalCDOObject> getProperContents(final InternalCDOObject object,
- final CDOTransaction transaction)
- {
- final boolean isResource = object instanceof Resource;
- final Iterator<EObject> delegate = object.eContents().iterator();
-
- return new Iterator<InternalCDOObject>()
- {
- private Object next;
-
- public boolean hasNext()
- {
- while (delegate.hasNext())
- {
- InternalEObject eObject = (InternalEObject)delegate.next();
- EStructuralFeature eContainingFeature = eObject.eContainingFeature();
- if (isResource || eObject.eDirectResource() == null
- && (eContainingFeature == null || EMFUtil.isPersistent(eContainingFeature)))
- {
- next = FSMUtil.adapt(eObject, transaction);
- return true;
- }
- }
-
- return false;
- }
-
- public InternalCDOObject next()
- {
- return (InternalCDOObject)next;
- }
-
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
- };
- }
- }
-
- /**
- * Attaches a tree of {@link PrepareTransition prepared} objects to a CDOView.
- * <p>
- * Execution is recursive and includes:
- * <ol>
- * <li>Calling {@link InternalCDOObject#cdoInternalPostAttach()},<br>
- * which includes for {@link CDOObjectImpl}:
- * <ol>
- * <li>Population of the CDORevision with the current values in
- * {@link EStoreEObjectImpl#eSetting(org.eclipse.emf.ecore.EStructuralFeature) eSettings}
- * <li>Unsetting {@link EStoreEObjectImpl#eSetting(org.eclipse.emf.ecore.EStructuralFeature) eSettings}
- * </ol>
- * <li>Changing state to {@link CDOState#NEW NEW}
- * </ol>
- *
- * @see PrepareTransition
- * @author Eike Stepper
- */
- private final class AttachTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
- {
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object NULL)
- {
- object.cdoInternalPostAttach();
- changeState(object, CDOState.NEW);
- }
- }
-
- /**
- * Bug 283985 (Re-attachment)
- *
- * @author Caspar De Groot
- */
- private final class ReattachTransition implements
- ITransition<CDOState, CDOEvent, InternalCDOObject, InternalCDOTransaction>
- {
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, InternalCDOTransaction transaction)
- {
- InternalCDORevisionManager revisionManager = transaction.getSession().getRevisionManager();
- InternalCDORevision cleanRevision = transaction.getCleanRevisions().get(object).copy();
- CDOID id = cleanRevision.getID();
-
- // Bug 373096: Determine clean revision of the CURRENT/LAST savepoint
- InternalCDOSavepoint savepoint = transaction.getFirstSavepoint();
- while (savepoint.getNextSavepoint() != null)
- {
- CDORevisionDelta delta = savepoint.getRevisionDeltas().get(id);
- if (delta != null)
- {
- delta.apply(cleanRevision);
- }
-
- savepoint = savepoint.getNextSavepoint();
- }
-
- object.cdoInternalSetID(id);
- object.cdoInternalSetView(transaction);
-
- // Construct a new revision
- CDORevisionFactory factory = revisionManager.getFactory();
- InternalCDORevision revision = (InternalCDORevision)factory.createRevision(object.eClass());
- revision.setID(id);
- revision.setBranchPoint(cleanRevision.getBranch().getHead());
- revision.setVersion(cleanRevision.getVersion());
-
- // Populate the revision based on the values in the CDOObject
- object.cdoInternalSetRevision(revision);
- object.cdoInternalPostAttach();
-
- // Compute a revision delta and register it with the tx
- CDORevisionDelta revisionDelta = revision.compare(cleanRevision);
- if (revisionDelta.isEmpty())
- {
- changeState(object, CDOState.CLEAN);
- }
- else
- {
- transaction.registerRevisionDelta(revisionDelta);
- transaction.registerDirty(object, (CDOFeatureDelta)null);
- changeState(object, CDOState.DIRTY);
- }
-
- // Add the object to the set of reattached objects
- Map<CDOID, CDOObject> reattachedObjects = transaction.getLastSavepoint().getReattachedObjects();
- reattachedObjects.put(id, object);
- }
- }
-
- /**
- * @author Eike Stepper
- */
- private static final class DetachTransition implements
- ITransition<CDOState, CDOEvent, InternalCDOObject, List<InternalCDOObject>>
- {
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event,
- List<InternalCDOObject> objectsToDetach)
- {
- InternalCDOTransaction transaction = (InternalCDOTransaction)object.cdoView();
- objectsToDetach.add(object);
- boolean isResource = object instanceof Resource;
-
- // Prepare content tree
- for (Iterator<EObject> it = object.eContents().iterator(); it.hasNext();)
- {
- InternalEObject eObject = (InternalEObject)it.next();
- boolean isDirectlyConnected = isResource && eObject.eDirectResource() == object;
- if (isDirectlyConnected || eObject.eDirectResource() == null)
- {
- InternalCDOObject content = FSMUtil.adapt(eObject, transaction);
- if (content != null)
- {
- INSTANCE.process(content, CDOEvent.DETACH, objectsToDetach);
- }
- }
- }
- }
- }
-
- /**
- * @author Eike Stepper
- */
- final private class CommitTransition implements
- ITransition<CDOState, CDOEvent, InternalCDOObject, CommitTransactionResult>
- {
- public CommitTransition(boolean useDeltas)
- {
- }
-
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, CommitTransactionResult data)
- {
- InternalCDOTransaction transaction = object.cdoView().toTransaction();
- InternalCDORevision revision = object.cdoRevision();
- Map<CDOID, CDOID> idMappings = data.getIDMappings();
-
- // Adjust object
- CDOID oldID = object.cdoID();
- CDOID newID = idMappings.get(oldID);
- if (newID != null)
- {
- object.cdoInternalSetID(newID);
- transaction.remapObject(oldID);
- revision.setID(newID);
- }
-
- // Adjust revision
- revision.adjustForCommit(transaction.getBranch(), data.getTimeStamp());
- revision.adjustReferences(data.getReferenceAdjuster());
- revision.freeze();
-
- InternalCDORevisionManager revisionManager = transaction.getSession().getRevisionManager();
- revisionManager.addRevision(revision);
-
- changeState(object, CDOState.CLEAN);
- }
- }
-
- /**
- * @author Eike Stepper
- */
- private final class RollbackTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
- {
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object NULL)
- {
- object.cdoInternalSetRevision(null);
- changeState(object, CDOState.PROXY);
- }
- }
-
- /**
- * @author Eike Stepper
- */
- private final class WriteTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
- {
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object featureDelta)
- {
- InternalCDOTransaction transaction = object.cdoView().toTransaction();
- InternalCDORevision cleanRevision = object.cdoRevision();
- transaction.getCleanRevisions().put(object, cleanRevision);
-
- // Copy revision
- InternalCDORevision revision = object.cdoRevision().copy();
- object.cdoInternalSetRevision(revision);
-
- transaction.registerDirty(object, (CDOFeatureDelta)featureDelta);
- changeState(object, CDOState.DIRTY);
- }
- }
-
- /**
- * @author Simon McDuff
- */
- private static final class WriteNewTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
- {
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object featureDelta)
- {
- InternalCDOTransaction transaction = object.cdoView().toTransaction();
- transaction.registerFeatureDelta(object, (CDOFeatureDelta)featureDelta);
- }
- }
-
- /**
- * @author Simon McDuff
- */
- private static final class RewriteTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
- {
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object featureDelta)
- {
- InternalCDOTransaction transaction = object.cdoView().toTransaction();
- transaction.registerFeatureDelta(object, (CDOFeatureDelta)featureDelta);
- }
- }
-
- /**
- * @author Simon McDuff
- */
- private static class DetachRemoteTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
- {
- static final DetachRemoteTransition INSTANCE = new DetachRemoteTransition();
-
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object NULL)
- {
- CDOStateMachine.INSTANCE.changeState(object, CDOState.INVALID);
-
- InternalCDOView view = object.cdoView();
- view.deregisterObject(object);
- object.cdoInternalPostDetach(true);
- }
- }
-
- /**
- * @author Eike Stepper
- */
- private class InvalidateTransition implements
- ITransition<CDOState, CDOEvent, InternalCDOObject, Pair<CDORevisionKey, Long>>
- {
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Pair<CDORevisionKey, Long> keyAndTime)
- {
- CDORevisionKey key = keyAndTime.getElement1();
- InternalCDORevision oldRevision = object.cdoRevision();
- if (key == null || key.getVersion() >= oldRevision.getVersion())
- {
- InternalCDOView view = object.cdoView();
-
- CDORevisionKey newKey = null;
- if (key != null)
- {
- int newVersion = getNewVersion(key);
- newKey = CDORevisionUtil.createRevisionKey(key.getID(), key.getBranch(), newVersion);
- }
-
- InternalCDORevision newRevision = null;
- if (newKey != null)
- {
- InternalCDORevisionCache cache = view.getSession().getRevisionManager().getCache();
- newRevision = (InternalCDORevision)cache.getRevisionByVersion(newKey.getID(), newKey);
- }
-
- if (newRevision != null)
- {
- object.cdoInternalSetRevision(newRevision);
- changeState(object, CDOState.CLEAN);
- object.cdoInternalPostLoad();
- }
- else
- {
- changeState(object, CDOState.PROXY);
-
- CDOInvalidationPolicy policy = view.options().getInvalidationPolicy();
- policy.handleInvalidation(object, key);
- object.cdoInternalPostInvalidate();
- }
- }
- }
-
- private int getNewVersion(CDORevisionKey key)
- {
- if (key instanceof CDORevisionDelta)
- {
- CDORevisionDelta delta = (CDORevisionDelta)key;
- CDORevisable target = delta.getTarget();
- if (target != null && key.getBranch() == target.getBranch())
- {
- return target.getVersion();
- }
- }
-
- return key.getVersion() + 1;
- }
- }
-
- /**
- * @author Eike Stepper
- * @since 2.0
- */
- private class ConflictTransition extends InvalidateTransition
- {
- @Override
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Pair<CDORevisionKey, Long> keyAndTime)
- {
- CDORevisionKey key = keyAndTime.getElement1();
- InternalCDORevision oldRevision = object.cdoRevision();
- if (key == null || key.getVersion() >= oldRevision.getVersion() - 1)
- {
- changeState(object, CDOState.CONFLICT);
- InternalCDOTransaction transaction = object.cdoView().toTransaction();
- transaction.setConflict(object);
- }
- }
- }
-
- /**
- * @author Simon McDuff
- */
- private final class InvalidConflictTransition extends ConflictTransition
- {
- @Override
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Pair<CDORevisionKey, Long> UNUSED)
- {
- changeState(object, CDOState.INVALID_CONFLICT);
-
- InternalCDOTransaction transaction = object.cdoView().toTransaction();
- transaction.setConflict(object);
- }
- }
-
- /**
- * @author Eike Stepper
- */
- private final class LoadTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
- {
- private boolean forWrite;
-
- public LoadTransition(boolean forWrite)
- {
- this.forWrite = forWrite;
- }
-
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object delta)
- {
- object.cdoInternalPreLoad();
-
- InternalCDOView view = object.cdoView();
- InternalCDORevision revision = view.getRevision(object.cdoID(), true);
- if (revision == null)
- {
- INSTANCE.detachRemote(object);
- CDOInvalidationPolicy policy = view.options().getInvalidationPolicy();
- policy.handleInvalidObject(object);
- }
-
- object.cdoInternalSetRevision(revision);
- changeState(object, CDOState.CLEAN);
- object.cdoInternalPostLoad();
-
- if (view.options().isLoadNotificationEnabled())
- {
- try
- {
- CDONotificationBuilder builder = new CDONotificationBuilder(view);
-
- NotificationChain notification = builder.buildNotification(object, revision);
- if (notification != null)
- {
- notification.dispatch();
- }
- }
- catch (PartialCollectionLoadingNotSupportedException ex)
- {
- if (TRACER.isEnabled())
- {
- TRACER.trace(ex);
- }
- }
- }
-
- if (forWrite)
- {
- INSTANCE.writeWithoutViewLock(object, (CDOFeatureDelta)delta);
- }
- }
- }
-
- /**
- * @author Simon McDuff
- */
- private static final class InvalidTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
- {
- public static final InvalidTransition INSTANCE = new InvalidTransition();
-
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object NULL)
- {
- InternalCDOView view = object.cdoView();
- CDOInvalidationPolicy policy = view.options().getInvalidationPolicy();
- policy.handleInvalidObject(object);
- }
- }
-}
-
-/**
- * @author Eike Stepper
- */
-enum CDOEvent
-{
- PREPARE, ATTACH, DETACH, REATTACH, READ, WRITE, INVALIDATE, DETACH_REMOTE, COMMIT, ROLLBACK
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Simon McDuff - maintenance
+ */
+package org.eclipse.emf.internal.cdo.view;
+
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.CDOState;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDTemp;
+import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.common.revision.CDORevisable;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionFactory;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.security.NoPermissionException;
+import org.eclipse.emf.cdo.common.util.PartialCollectionLoadingNotSupportedException;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.view.CDOInvalidationPolicy;
+import org.eclipse.emf.cdo.view.CDOView;
+
+import org.eclipse.emf.internal.cdo.CDOObjectImpl;
+import org.eclipse.emf.internal.cdo.bundle.OM;
+import org.eclipse.emf.internal.cdo.object.CDONotificationBuilder;
+
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.fsm.FiniteStateMachine;
+import org.eclipse.net4j.util.fsm.ITransition;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.common.notify.NotificationChain;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.impl.EStoreEObjectImpl;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.CommitTransactionResult;
+import org.eclipse.emf.spi.cdo.FSMUtil;
+import org.eclipse.emf.spi.cdo.InternalCDOObject;
+import org.eclipse.emf.spi.cdo.InternalCDOSavepoint;
+import org.eclipse.emf.spi.cdo.InternalCDOSession;
+import org.eclipse.emf.spi.cdo.InternalCDOTransaction;
+import org.eclipse.emf.spi.cdo.InternalCDOView;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent, InternalCDOObject>
+{
+ // @Singleton
+ public static final CDOStateMachine INSTANCE = new CDOStateMachine();
+
+ private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_STATEMACHINE, CDOStateMachine.class);
+
+ private InternalCDOObject lastTracedObject;
+
+ private CDOState lastTracedState;
+
+ private CDOEvent lastTracedEvent;
+
+ @SuppressWarnings("unchecked")
+ private CDOStateMachine()
+ {
+ super(CDOState.class, CDOEvent.class);
+
+ init(CDOState.TRANSIENT, CDOEvent.PREPARE, new PrepareTransition());
+ init(CDOState.TRANSIENT, CDOEvent.ATTACH, FAIL);
+ init(CDOState.TRANSIENT, CDOEvent.DETACH, IGNORE);
+ init(CDOState.TRANSIENT, CDOEvent.REATTACH, new ReattachTransition());
+ init(CDOState.TRANSIENT, CDOEvent.READ, IGNORE);
+ init(CDOState.TRANSIENT, CDOEvent.WRITE, IGNORE);
+ init(CDOState.TRANSIENT, CDOEvent.INVALIDATE, IGNORE);
+ init(CDOState.TRANSIENT, CDOEvent.DETACH_REMOTE, IGNORE);
+ init(CDOState.TRANSIENT, CDOEvent.COMMIT, FAIL);
+ init(CDOState.TRANSIENT, CDOEvent.ROLLBACK, FAIL);
+
+ init(CDOState.PREPARED, CDOEvent.PREPARE, FAIL);
+ init(CDOState.PREPARED, CDOEvent.ATTACH, new AttachTransition());
+ init(CDOState.PREPARED, CDOEvent.DETACH, FAIL);
+ init(CDOState.PREPARED, CDOEvent.REATTACH, FAIL);
+ init(CDOState.PREPARED, CDOEvent.READ, IGNORE);
+ init(CDOState.PREPARED, CDOEvent.WRITE, FAIL);
+ init(CDOState.PREPARED, CDOEvent.INVALIDATE, FAIL);
+ init(CDOState.PREPARED, CDOEvent.DETACH_REMOTE, FAIL);
+ init(CDOState.PREPARED, CDOEvent.COMMIT, FAIL);
+ init(CDOState.PREPARED, CDOEvent.ROLLBACK, FAIL);
+
+ init(CDOState.NEW, CDOEvent.PREPARE, FAIL);
+ init(CDOState.NEW, CDOEvent.ATTACH, FAIL);
+ init(CDOState.NEW, CDOEvent.DETACH, new DetachTransition());
+ init(CDOState.NEW, CDOEvent.REATTACH, FAIL);
+ init(CDOState.NEW, CDOEvent.READ, IGNORE);
+ init(CDOState.NEW, CDOEvent.WRITE, new WriteNewTransition());
+ init(CDOState.NEW, CDOEvent.INVALIDATE, FAIL);
+ init(CDOState.NEW, CDOEvent.DETACH_REMOTE, FAIL);
+ init(CDOState.NEW, CDOEvent.COMMIT, new CommitTransition(false));
+ init(CDOState.NEW, CDOEvent.ROLLBACK, FAIL);
+
+ init(CDOState.CLEAN, CDOEvent.PREPARE, FAIL);
+ init(CDOState.CLEAN, CDOEvent.ATTACH, FAIL);
+ init(CDOState.CLEAN, CDOEvent.DETACH, new DetachTransition());
+ init(CDOState.CLEAN, CDOEvent.REATTACH, FAIL);
+ init(CDOState.CLEAN, CDOEvent.READ, IGNORE);
+ init(CDOState.CLEAN, CDOEvent.WRITE, new WriteTransition());
+ init(CDOState.CLEAN, CDOEvent.INVALIDATE, new InvalidateTransition());
+ init(CDOState.CLEAN, CDOEvent.DETACH_REMOTE, DetachRemoteTransition.INSTANCE);
+ init(CDOState.CLEAN, CDOEvent.COMMIT, FAIL);
+ init(CDOState.CLEAN, CDOEvent.ROLLBACK, FAIL);
+
+ init(CDOState.DIRTY, CDOEvent.PREPARE, FAIL);
+ init(CDOState.DIRTY, CDOEvent.ATTACH, FAIL);
+ init(CDOState.DIRTY, CDOEvent.DETACH, new DetachTransition());
+ init(CDOState.DIRTY, CDOEvent.REATTACH, FAIL);
+ init(CDOState.DIRTY, CDOEvent.READ, IGNORE);
+ init(CDOState.DIRTY, CDOEvent.WRITE, new RewriteTransition());
+ init(CDOState.DIRTY, CDOEvent.INVALIDATE, new ConflictTransition());
+ init(CDOState.DIRTY, CDOEvent.DETACH_REMOTE, new InvalidConflictTransition());
+ init(CDOState.DIRTY, CDOEvent.COMMIT, new CommitTransition(true));
+ init(CDOState.DIRTY, CDOEvent.ROLLBACK, new RollbackTransition());
+
+ init(CDOState.PROXY, CDOEvent.PREPARE, FAIL);
+ init(CDOState.PROXY, CDOEvent.ATTACH, FAIL);
+ init(CDOState.PROXY, CDOEvent.DETACH, new DetachTransition());
+ init(CDOState.PROXY, CDOEvent.REATTACH, FAIL);
+ init(CDOState.PROXY, CDOEvent.READ, new LoadTransition(false));
+ init(CDOState.PROXY, CDOEvent.WRITE, new LoadTransition(true));
+ init(CDOState.PROXY, CDOEvent.INVALIDATE, IGNORE);
+ init(CDOState.PROXY, CDOEvent.DETACH_REMOTE, DetachRemoteTransition.INSTANCE);
+ init(CDOState.PROXY, CDOEvent.COMMIT, FAIL);
+ init(CDOState.PROXY, CDOEvent.ROLLBACK, FAIL);
+
+ init(CDOState.CONFLICT, CDOEvent.PREPARE, FAIL);
+ init(CDOState.CONFLICT, CDOEvent.ATTACH, IGNORE);
+ init(CDOState.CONFLICT, CDOEvent.DETACH, new DetachTransition());
+ init(CDOState.CONFLICT, CDOEvent.REATTACH, FAIL);
+ init(CDOState.CONFLICT, CDOEvent.READ, IGNORE);
+ init(CDOState.CONFLICT, CDOEvent.WRITE, new RewriteTransition());
+ init(CDOState.CONFLICT, CDOEvent.INVALIDATE, IGNORE);
+ init(CDOState.CONFLICT, CDOEvent.DETACH_REMOTE, IGNORE);
+ init(CDOState.CONFLICT, CDOEvent.COMMIT, IGNORE);
+ init(CDOState.CONFLICT, CDOEvent.ROLLBACK, new RollbackTransition());
+
+ init(CDOState.INVALID, CDOEvent.PREPARE, InvalidTransition.INSTANCE);
+ init(CDOState.INVALID, CDOEvent.ATTACH, InvalidTransition.INSTANCE);
+ init(CDOState.INVALID, CDOEvent.DETACH, InvalidTransition.INSTANCE);
+ init(CDOState.INVALID, CDOEvent.REATTACH, FAIL);
+ init(CDOState.INVALID, CDOEvent.READ, InvalidTransition.INSTANCE);
+ init(CDOState.INVALID, CDOEvent.WRITE, InvalidTransition.INSTANCE);
+ init(CDOState.INVALID, CDOEvent.INVALIDATE, IGNORE); // TODO Handle changeViewTarget!!!
+ init(CDOState.INVALID, CDOEvent.DETACH_REMOTE, IGNORE);
+ init(CDOState.INVALID, CDOEvent.COMMIT, InvalidTransition.INSTANCE);
+ init(CDOState.INVALID, CDOEvent.ROLLBACK, InvalidTransition.INSTANCE);
+
+ init(CDOState.INVALID_CONFLICT, CDOEvent.PREPARE, InvalidTransition.INSTANCE);
+ init(CDOState.INVALID_CONFLICT, CDOEvent.ATTACH, InvalidTransition.INSTANCE);
+ init(CDOState.INVALID_CONFLICT, CDOEvent.DETACH, InvalidTransition.INSTANCE);
+ init(CDOState.INVALID_CONFLICT, CDOEvent.REATTACH, FAIL);
+ init(CDOState.INVALID_CONFLICT, CDOEvent.READ, IGNORE);
+ init(CDOState.INVALID_CONFLICT, CDOEvent.WRITE, IGNORE);
+ init(CDOState.INVALID_CONFLICT, CDOEvent.INVALIDATE, IGNORE);
+ init(CDOState.INVALID_CONFLICT, CDOEvent.DETACH_REMOTE, IGNORE);
+ init(CDOState.INVALID_CONFLICT, CDOEvent.COMMIT, InvalidTransition.INSTANCE);
+ init(CDOState.INVALID_CONFLICT, CDOEvent.ROLLBACK, DetachRemoteTransition.INSTANCE);
+ }
+
+ /**
+ * The object is already attached in EMF world. It contains all the information needed to know where it will be
+ * connected.
+ *
+ * @since 2.0
+ */
+ public void attach(InternalCDOObject object, InternalCDOTransaction transaction)
+ {
+ synchronized (transaction)
+ {
+ List<InternalCDOObject> contents = new ArrayList<InternalCDOObject>();
+ prepare(object, new Pair<InternalCDOTransaction, List<InternalCDOObject>>(transaction, contents));
+
+ attachOrReattach(object, transaction);
+ for (InternalCDOObject content : contents)
+ {
+ attachOrReattach(content, transaction);
+ }
+ }
+ }
+
+ private void attachOrReattach(InternalCDOObject object, InternalCDOTransaction transaction)
+ {
+ // Bug 283985 (Re-attachment):
+ // If the object going through a prepareTransition is present in cleanRevisions,
+ // then it was detached earlier, and so we can infer that it is being re-attached
+ if (transaction.getCleanRevisions().containsKey(object))
+ {
+ reattachObject(object, transaction);
+ }
+ else
+ {
+ attachObject(object);
+ }
+ }
+
+ /**
+ * Phase 1: TRANSIENT --> PREPARED
+ */
+ private void prepare(InternalCDOObject object,
+ Pair<InternalCDOTransaction, List<InternalCDOObject>> transactionAndContents)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("PREPARE: {0} --> {1}", object, transactionAndContents.getElement1()); //$NON-NLS-1$
+ }
+
+ process(object, CDOEvent.PREPARE, transactionAndContents);
+ }
+
+ /**
+ * Phase 2: PREPARED --> NEW
+ */
+ private void attachObject(InternalCDOObject object)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("ATTACH: {0}", object); //$NON-NLS-1$
+ }
+
+ process(object, CDOEvent.ATTACH, null);
+ }
+
+ private void reattachObject(InternalCDOObject object, InternalCDOTransaction transaction)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("REATTACH: {0}", object);
+ }
+
+ process(object, CDOEvent.REATTACH, transaction);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void detach(InternalCDOObject object)
+ {
+ synchronized (getMonitor(object))
+ {
+ if (TRACER.isEnabled())
+ {
+ trace(object, CDOEvent.DETACH);
+ }
+
+ List<InternalCDOObject> objectsToDetach = new ArrayList<InternalCDOObject>();
+ InternalCDOTransaction transaction = (InternalCDOTransaction)object.cdoView();
+
+ // Accumulate objects that needs to be detached
+ // If we have an error, we will keep the graph exactly like it was before.
+ process(object, CDOEvent.DETACH, objectsToDetach);
+
+ // postDetach requires the object to be TRANSIENT
+ for (InternalCDOObject content : objectsToDetach)
+ {
+ CDOState oldState = content.cdoInternalSetState(CDOState.TRANSIENT);
+ content.cdoInternalPostDetach(false);
+ content.cdoInternalSetState(oldState);
+ }
+
+ // detachObject needs to know the state before we change the object to TRANSIENT
+ for (InternalCDOObject content : objectsToDetach)
+ {
+ transaction.detachObject(content);
+ content.cdoInternalSetState(CDOState.TRANSIENT);
+
+ content.cdoInternalSetView(null);
+ content.cdoInternalSetID(null);
+ content.cdoInternalSetRevision(null);
+ }
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public InternalCDORevision read(InternalCDOObject object)
+ {
+ synchronized (getMonitor(object))
+ {
+ if (TRACER.isEnabled())
+ {
+ trace(object, CDOEvent.READ);
+ }
+
+ process(object, CDOEvent.READ, null);
+
+ return object.cdoRevision();
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public InternalCDORevision readNoLoad(InternalCDOObject object)
+ {
+ synchronized (getMonitor(object))
+ {
+ switch (object.cdoState())
+ {
+ case TRANSIENT:
+ case PREPARED:
+ case NEW:
+ case CONFLICT:
+ case INVALID_CONFLICT:
+ case INVALID:
+ case PROXY:
+ return null;
+ }
+
+ return object.cdoRevision();
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void write(InternalCDOObject object)
+ {
+ write(object, null);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void write(InternalCDOObject object, CDOFeatureDelta featureDelta)
+ {
+ synchronized (getMonitor(object))
+ {
+ writeWithoutViewLock(object, featureDelta);
+ }
+ }
+
+ private void writeWithoutViewLock(InternalCDOObject object, CDOFeatureDelta featureDelta)
+ {
+ if (TRACER.isEnabled())
+ {
+ trace(object, CDOEvent.WRITE);
+ }
+
+ process(object, CDOEvent.WRITE, featureDelta);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void reload(InternalCDOObject... objects)
+ {
+ if (objects == null || objects.length == 0)
+ {
+ return;
+ }
+
+ synchronized (getMonitor(objects[0]))
+ {
+ for (InternalCDOObject object : objects)
+ {
+ CDOState state = object.cdoState();
+ if (state == CDOState.CLEAN || state == CDOState.PROXY)
+ {
+ changeState(object, CDOState.PROXY);
+ object.cdoInternalSetRevision(null);
+ read(object);
+ }
+ }
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void invalidate(InternalCDOObject object, CDORevisionKey key, long lastUpdateTime)
+ {
+ synchronized (getMonitor(object))
+ {
+ if (TRACER.isEnabled())
+ {
+ trace(object, CDOEvent.INVALIDATE);
+ }
+
+ process(object, CDOEvent.INVALIDATE, new Pair<CDORevisionKey, Long>(key, lastUpdateTime));
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void detachRemote(InternalCDOObject object)
+ {
+ synchronized (getMonitor(object))
+ {
+ if (TRACER.isEnabled())
+ {
+ trace(object, CDOEvent.DETACH_REMOTE);
+ }
+
+ process(object, CDOEvent.DETACH_REMOTE, null);
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void commit(InternalCDOObject object, CommitTransactionResult result)
+ {
+ synchronized (getMonitor(object))
+ {
+ if (TRACER.isEnabled())
+ {
+ trace(object, CDOEvent.COMMIT);
+ }
+
+ process(object, CDOEvent.COMMIT, result);
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void rollback(InternalCDOObject object)
+ {
+ synchronized (getMonitor(object))
+ {
+ if (TRACER.isEnabled())
+ {
+ trace(object, CDOEvent.ROLLBACK);
+ }
+
+ process(object, CDOEvent.ROLLBACK, null);
+ object.cdoInternalPostRollback();
+ }
+ }
+
+ @Override
+ protected CDOState getState(InternalCDOObject object)
+ {
+ return object.cdoState();
+ }
+
+ @Override
+ protected void setState(InternalCDOObject object, CDOState state)
+ {
+ object.cdoInternalSetState(state);
+ }
+
+ private Object getMonitor(InternalCDOObject object)
+ {
+ InternalCDOView view = object.cdoView();
+ if (view != null)
+ {
+ return view;
+ }
+
+ // In TRANSIENT and PREPARED the object is not yet attached to a view
+ return object;
+ }
+
+ /**
+ * Removes clutter from the trace log
+ */
+ private void trace(InternalCDOObject object, CDOEvent event)
+ {
+ CDOState state = object.cdoState();
+ if (lastTracedObject != object || lastTracedState != state || lastTracedEvent != event)
+ {
+ TRACER.format("{0}: {1}", event, object.getClass().getName()); //$NON-NLS-1$
+ lastTracedObject = object;
+ lastTracedState = state;
+ lastTracedEvent = event;
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private void testAttach(InternalCDOObject object)
+ {
+ process(object, CDOEvent.ATTACH, null);
+ }
+
+ /**
+ * Prepares a tree of transient objects to be subsequently {@link AttachTransition attached} to a CDOView.
+ * <p>
+ * Execution is recursive and includes:
+ * <ol>
+ * <li>Assignment of a new {@link CDOIDTemp}
+ * <li>Assignment of a new {@link CDORevision}
+ * <li>Bidirectional association with the {@link CDOView}
+ * <li>Registration with the {@link CDOTransaction}
+ * <li>Changing state to {@link CDOState#PREPARED PREPARED}
+ * </ol>
+ *
+ * @see AttachTransition
+ * @author Eike Stepper
+ */
+ private final class PrepareTransition implements
+ ITransition<CDOState, CDOEvent, InternalCDOObject, Pair<InternalCDOTransaction, List<InternalCDOObject>>>
+ {
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event,
+ Pair<InternalCDOTransaction, List<InternalCDOObject>> transactionAndContents)
+ {
+ InternalCDOTransaction transaction = transactionAndContents.getElement1();
+ List<InternalCDOObject> contents = transactionAndContents.getElement2();
+
+ // If the object going through a prepareTransition is present in cleanRevisions,
+ // then it was detached earlier, and so we can infer that it is being re-attached
+ boolean reattaching = transaction.getCleanRevisions().containsKey(object);
+
+ if (!reattaching)
+ {
+ // Prepare object
+ CDOID id = transaction.createIDForNewObject(object.cdoInternalInstance());
+ object.cdoInternalSetID(id);
+ object.cdoInternalSetView(transaction);
+ changeState(object, CDOState.PREPARED);
+
+ // Create new revision
+ EClass eClass = object.eClass();
+ InternalCDOSession session = transaction.getSession();
+ checkPackageRegistrationProblems(session, eClass);
+
+ CDORevisionFactory factory = session.getRevisionManager().getFactory();
+ InternalCDORevision revision = (InternalCDORevision)factory.createRevision(eClass);
+ revision.setID(id);
+ revision.setBranchPoint(transaction.getBranch().getHead());
+
+ object.cdoInternalSetRevision(revision);
+
+ // Register object
+ transaction.registerObject(object);
+ }
+
+ transaction.registerAttached(object, !reattaching);
+
+ // Prepare content tree
+ for (Iterator<InternalCDOObject> it = getProperContents(object, transaction); it.hasNext();)
+ {
+ InternalCDOObject content = it.next();
+ contents.add(content);
+ INSTANCE.process(content, CDOEvent.PREPARE, transactionAndContents);
+ }
+ }
+
+ private void checkPackageRegistrationProblems(InternalCDOSession session, EClass eClass)
+ {
+ if (session.options().isGeneratedPackageEmulationEnabled())
+ {
+ // Check that there are no multiple EPackages with the same URI in system. Bug 335004
+ String packageURI = eClass.getEPackage().getNsURI();
+ Object packageObject = session.getPackageRegistry().get(packageURI);
+ if (packageObject instanceof InternalCDOPackageInfo)
+ {
+ packageObject = ((InternalCDOPackageInfo)packageObject).getEPackage(false);
+ }
+
+ if (packageObject instanceof EPackage && packageObject != eClass.getEPackage())
+ {
+ throw new IllegalStateException(MessageFormat.format(
+ "Global EPackage {0} for EClass {1} is different from EPackage found in CDOPackageRegistry", packageURI,
+ eClass));
+ }
+ }
+ }
+
+ private Iterator<InternalCDOObject> getProperContents(final InternalCDOObject object,
+ final CDOTransaction transaction)
+ {
+ final boolean isResource = object instanceof Resource;
+ final Iterator<EObject> delegate = object.eContents().iterator();
+
+ return new Iterator<InternalCDOObject>()
+ {
+ private Object next;
+
+ public boolean hasNext()
+ {
+ while (delegate.hasNext())
+ {
+ InternalEObject eObject = (InternalEObject)delegate.next();
+ EStructuralFeature eContainingFeature = eObject.eContainingFeature();
+ if (isResource || eObject.eDirectResource() == null
+ && (eContainingFeature == null || EMFUtil.isPersistent(eContainingFeature)))
+ {
+ next = FSMUtil.adapt(eObject, transaction);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public InternalCDOObject next()
+ {
+ return (InternalCDOObject)next;
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ }
+
+ /**
+ * Attaches a tree of {@link PrepareTransition prepared} objects to a CDOView.
+ * <p>
+ * Execution is recursive and includes:
+ * <ol>
+ * <li>Calling {@link InternalCDOObject#cdoInternalPostAttach()},<br>
+ * which includes for {@link CDOObjectImpl}:
+ * <ol>
+ * <li>Population of the CDORevision with the current values in
+ * {@link EStoreEObjectImpl#eSetting(org.eclipse.emf.ecore.EStructuralFeature) eSettings}
+ * <li>Unsetting {@link EStoreEObjectImpl#eSetting(org.eclipse.emf.ecore.EStructuralFeature) eSettings}
+ * </ol>
+ * <li>Changing state to {@link CDOState#NEW NEW}
+ * </ol>
+ *
+ * @see PrepareTransition
+ * @author Eike Stepper
+ */
+ private final class AttachTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
+ {
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object NULL)
+ {
+ object.cdoInternalPostAttach();
+ changeState(object, CDOState.NEW);
+ }
+ }
+
+ /**
+ * Bug 283985 (Re-attachment)
+ *
+ * @author Caspar De Groot
+ */
+ private final class ReattachTransition implements
+ ITransition<CDOState, CDOEvent, InternalCDOObject, InternalCDOTransaction>
+ {
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, InternalCDOTransaction transaction)
+ {
+ InternalCDORevisionManager revisionManager = transaction.getSession().getRevisionManager();
+ InternalCDORevision cleanRevision = transaction.getCleanRevisions().get(object).copy();
+ CDOID id = cleanRevision.getID();
+
+ // Bug 373096: Determine clean revision of the CURRENT/LAST savepoint
+ InternalCDOSavepoint savepoint = transaction.getFirstSavepoint();
+ while (savepoint.getNextSavepoint() != null)
+ {
+ CDORevisionDelta delta = savepoint.getRevisionDeltas().get(id);
+ if (delta != null)
+ {
+ delta.apply(cleanRevision);
+ }
+
+ savepoint = savepoint.getNextSavepoint();
+ }
+
+ object.cdoInternalSetID(id);
+ object.cdoInternalSetView(transaction);
+
+ // Construct a new revision
+ CDORevisionFactory factory = revisionManager.getFactory();
+ InternalCDORevision revision = (InternalCDORevision)factory.createRevision(object.eClass());
+ revision.setID(id);
+ revision.setBranchPoint(cleanRevision.getBranch().getHead());
+ revision.setVersion(cleanRevision.getVersion());
+
+ // Populate the revision based on the values in the CDOObject
+ object.cdoInternalSetRevision(revision);
+ object.cdoInternalPostAttach();
+
+ // Compute a revision delta and register it with the tx
+ CDORevisionDelta revisionDelta = revision.compare(cleanRevision);
+ if (revisionDelta.isEmpty())
+ {
+ changeState(object, CDOState.CLEAN);
+ }
+ else
+ {
+ transaction.registerRevisionDelta(revisionDelta);
+ transaction.registerDirty(object, (CDOFeatureDelta)null);
+ changeState(object, CDOState.DIRTY);
+ }
+
+ // Add the object to the set of reattached objects
+ Map<CDOID, CDOObject> reattachedObjects = transaction.getLastSavepoint().getReattachedObjects();
+ reattachedObjects.put(id, object);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class DetachTransition implements
+ ITransition<CDOState, CDOEvent, InternalCDOObject, List<InternalCDOObject>>
+ {
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event,
+ List<InternalCDOObject> objectsToDetach)
+ {
+ InternalCDOTransaction transaction = (InternalCDOTransaction)object.cdoView();
+ objectsToDetach.add(object);
+ boolean isResource = object instanceof Resource;
+
+ // Prepare content tree
+ for (Iterator<EObject> it = object.eContents().iterator(); it.hasNext();)
+ {
+ InternalEObject eObject = (InternalEObject)it.next();
+ boolean isDirectlyConnected = isResource && eObject.eDirectResource() == object;
+ if (isDirectlyConnected || eObject.eDirectResource() == null)
+ {
+ InternalCDOObject content = FSMUtil.adapt(eObject, transaction);
+ if (content != null)
+ {
+ INSTANCE.process(content, CDOEvent.DETACH, objectsToDetach);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ final private class CommitTransition implements
+ ITransition<CDOState, CDOEvent, InternalCDOObject, CommitTransactionResult>
+ {
+ public CommitTransition(boolean useDeltas)
+ {
+ }
+
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, CommitTransactionResult data)
+ {
+ InternalCDOTransaction transaction = object.cdoView().toTransaction();
+ InternalCDORevision revision = object.cdoRevision();
+ Map<CDOID, CDOID> idMappings = data.getIDMappings();
+
+ // Adjust object
+ CDOID oldID = object.cdoID();
+ CDOID newID = idMappings.get(oldID);
+ if (newID != null)
+ {
+ object.cdoInternalSetID(newID);
+ transaction.remapObject(oldID);
+ revision.setID(newID);
+ }
+
+ // Adjust revision
+ revision.adjustForCommit(transaction.getBranch(), data.getTimeStamp());
+ revision.adjustReferences(data.getReferenceAdjuster());
+ revision.freeze();
+
+ InternalCDORevisionManager revisionManager = transaction.getSession().getRevisionManager();
+ revisionManager.addRevision(revision);
+
+ changeState(object, CDOState.CLEAN);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private final class RollbackTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
+ {
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object NULL)
+ {
+ object.cdoInternalSetRevision(null);
+ changeState(object, CDOState.PROXY);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private final class WriteTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
+ {
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object featureDelta)
+ {
+ InternalCDOTransaction transaction = object.cdoView().toTransaction();
+ InternalCDORevision cleanRevision = object.cdoRevision();
+ if (!cleanRevision.isWritable())
+ {
+ throw new NoPermissionException(cleanRevision);
+ }
+
+ transaction.getCleanRevisions().put(object, cleanRevision);
+
+ // Copy revision
+ InternalCDORevision revision = object.cdoRevision().copy();
+ object.cdoInternalSetRevision(revision);
+
+ transaction.registerDirty(object, (CDOFeatureDelta)featureDelta);
+ changeState(object, CDOState.DIRTY);
+ }
+ }
+
+ /**
+ * @author Simon McDuff
+ */
+ private static final class WriteNewTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
+ {
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object featureDelta)
+ {
+ InternalCDORevision revision = object.cdoRevision();
+ if (!revision.isWritable())
+ {
+ throw new NoPermissionException(revision);
+ }
+
+ InternalCDOTransaction transaction = object.cdoView().toTransaction();
+ transaction.registerFeatureDelta(object, (CDOFeatureDelta)featureDelta);
+ }
+ }
+
+ /**
+ * @author Simon McDuff
+ */
+ private static final class RewriteTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
+ {
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object featureDelta)
+ {
+ InternalCDORevision revision = object.cdoRevision();
+ if (!revision.isWritable())
+ {
+ throw new NoPermissionException(revision);
+ }
+
+ InternalCDOTransaction transaction = object.cdoView().toTransaction();
+ transaction.registerFeatureDelta(object, (CDOFeatureDelta)featureDelta);
+ }
+ }
+
+ /**
+ * @author Simon McDuff
+ */
+ private static class DetachRemoteTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
+ {
+ static final DetachRemoteTransition INSTANCE = new DetachRemoteTransition();
+
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object NULL)
+ {
+ CDOStateMachine.INSTANCE.changeState(object, CDOState.INVALID);
+
+ InternalCDOView view = object.cdoView();
+ view.deregisterObject(object);
+ object.cdoInternalPostDetach(true);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private class InvalidateTransition implements
+ ITransition<CDOState, CDOEvent, InternalCDOObject, Pair<CDORevisionKey, Long>>
+ {
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Pair<CDORevisionKey, Long> keyAndTime)
+ {
+ CDORevisionKey key = keyAndTime.getElement1();
+ InternalCDORevision oldRevision = object.cdoRevision();
+ if (key == null || key.getVersion() >= oldRevision.getVersion())
+ {
+ InternalCDOView view = object.cdoView();
+
+ CDORevisionKey newKey = null;
+ if (key != null)
+ {
+ int newVersion = getNewVersion(key);
+ newKey = CDORevisionUtil.createRevisionKey(key.getID(), key.getBranch(), newVersion);
+ }
+
+ InternalCDORevision newRevision = null;
+ if (newKey != null)
+ {
+ InternalCDORevisionCache cache = view.getSession().getRevisionManager().getCache();
+ newRevision = (InternalCDORevision)cache.getRevisionByVersion(newKey.getID(), newKey);
+ }
+
+ if (newRevision != null)
+ {
+ object.cdoInternalSetRevision(newRevision);
+ changeState(object, CDOState.CLEAN);
+ object.cdoInternalPostLoad();
+ }
+ else
+ {
+ changeState(object, CDOState.PROXY);
+
+ CDOInvalidationPolicy policy = view.options().getInvalidationPolicy();
+ policy.handleInvalidation(object, key);
+ object.cdoInternalPostInvalidate();
+ }
+ }
+ }
+
+ private int getNewVersion(CDORevisionKey key)
+ {
+ if (key instanceof CDORevisionDelta)
+ {
+ CDORevisionDelta delta = (CDORevisionDelta)key;
+ CDORevisable target = delta.getTarget();
+ if (target != null && key.getBranch() == target.getBranch())
+ {
+ return target.getVersion();
+ }
+ }
+
+ return key.getVersion() + 1;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+ private class ConflictTransition extends InvalidateTransition
+ {
+ @Override
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Pair<CDORevisionKey, Long> keyAndTime)
+ {
+ CDORevisionKey key = keyAndTime.getElement1();
+ InternalCDORevision oldRevision = object.cdoRevision();
+ if (key == null || key.getVersion() >= oldRevision.getVersion() - 1)
+ {
+ changeState(object, CDOState.CONFLICT);
+ InternalCDOTransaction transaction = object.cdoView().toTransaction();
+ transaction.setConflict(object);
+ }
+ }
+ }
+
+ /**
+ * @author Simon McDuff
+ */
+ private final class InvalidConflictTransition extends ConflictTransition
+ {
+ @Override
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Pair<CDORevisionKey, Long> UNUSED)
+ {
+ changeState(object, CDOState.INVALID_CONFLICT);
+
+ InternalCDOTransaction transaction = object.cdoView().toTransaction();
+ transaction.setConflict(object);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private final class LoadTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
+ {
+ private boolean forWrite;
+
+ public LoadTransition(boolean forWrite)
+ {
+ this.forWrite = forWrite;
+ }
+
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object delta)
+ {
+ object.cdoInternalPreLoad();
+
+ InternalCDOView view = object.cdoView();
+ InternalCDORevision revision = view.getRevision(object.cdoID(), true);
+ if (revision == null)
+ {
+ INSTANCE.detachRemote(object);
+ CDOInvalidationPolicy policy = view.options().getInvalidationPolicy();
+ policy.handleInvalidObject(object);
+ }
+
+ if (forWrite && !revision.isWritable())
+ {
+ throw new NoPermissionException(revision);
+ }
+
+ object.cdoInternalSetRevision(revision);
+ changeState(object, CDOState.CLEAN);
+ object.cdoInternalPostLoad();
+
+ if (view.options().isLoadNotificationEnabled())
+ {
+ try
+ {
+ CDONotificationBuilder builder = new CDONotificationBuilder(view);
+
+ NotificationChain notification = builder.buildNotification(object, revision);
+ if (notification != null)
+ {
+ notification.dispatch();
+ }
+ }
+ catch (PartialCollectionLoadingNotSupportedException ex)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.trace(ex);
+ }
+ }
+ }
+
+ if (forWrite)
+ {
+ INSTANCE.writeWithoutViewLock(object, (CDOFeatureDelta)delta);
+ }
+ }
+ }
+
+ /**
+ * @author Simon McDuff
+ */
+ private static final class InvalidTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
+ {
+ public static final InvalidTransition INSTANCE = new InvalidTransition();
+
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object NULL)
+ {
+ InternalCDOView view = object.cdoView();
+ CDOInvalidationPolicy policy = view.options().getInvalidationPolicy();
+ policy.handleInvalidObject(object);
+ }
+ }
+}
+
+/**
+ * @author Eike Stepper
+ */
+enum CDOEvent
+{
+ PREPARE, ATTACH, DETACH, REATTACH, READ, WRITE, INVALIDATE, DETACH_REMOTE, COMMIT, ROLLBACK
+}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java
index 672b103e39..3134378695 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java
@@ -1,711 +1,716 @@
-/*
- * Copyright (c) 2004 - 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
- * Simon McDuff - bug 201266
- * Eike Stepper & Simon McDuff - bug 204890
- * Simon McDuff - bug 246705
- * Simon McDuff - bug 246622
- */
-package org.eclipse.emf.internal.cdo.view;
-
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.model.CDOModelUtil;
-import org.eclipse.emf.cdo.common.model.CDOType;
-import org.eclipse.emf.cdo.common.revision.CDOElementProxy;
-import org.eclipse.emf.cdo.common.revision.CDOList;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
-import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
-import org.eclipse.emf.cdo.eresource.CDOResource;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOAddFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOClearFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOContainerFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOMoveFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDORemoveFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOSetFeatureDeltaImpl;
-import org.eclipse.emf.cdo.internal.common.revision.delta.CDOUnsetFeatureDeltaImpl;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
-import org.eclipse.emf.cdo.util.ObjectNotFoundException;
-import org.eclipse.emf.cdo.view.CDOFeatureAnalyzer;
-import org.eclipse.emf.cdo.view.CDORevisionPrefetchingPolicy;
-
-import org.eclipse.emf.internal.cdo.bundle.OM;
-
-import org.eclipse.net4j.util.ObjectUtil;
-import org.eclipse.net4j.util.om.trace.ContextTracer;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.EcorePackage;
-import org.eclipse.emf.ecore.InternalEObject;
-import org.eclipse.emf.ecore.InternalEObject.EStore;
-import org.eclipse.emf.ecore.util.FeatureMap;
-import org.eclipse.emf.ecore.util.FeatureMapUtil;
-import org.eclipse.emf.spi.cdo.CDOStore;
-import org.eclipse.emf.spi.cdo.FSMUtil;
-import org.eclipse.emf.spi.cdo.InternalCDOObject;
-import org.eclipse.emf.spi.cdo.InternalCDOView;
-
-import java.text.MessageFormat;
-import java.util.List;
-
-/**
- * CDORevision needs to follow these rules:<br>
- * - Keep CDOID only when the object (!isNew && !isTransient) // Only when CDOID will not changed.<br>
- * - Keep EObject for external reference, new, transient and that until commit time.<br>
- * It is important since these objects could changed and we need to keep a reference to {@link EObject} until the end.
- * It is the reason why {@link CDOStoreImpl} always call {@link InternalCDOView#convertObjectToID(Object, boolean)} with
- * true.
- *
- * @author Eike Stepper
- */
-public final class CDOStoreImpl implements CDOStore
-{
- private final ContextTracer TRACER = new ContextTracer(OM.DEBUG_STORE, CDOStoreImpl.class);
-
- private InternalCDOView view;
-
- /**
- * @since 2.0
- */
- public CDOStoreImpl(InternalCDOView view)
- {
- this.view = view;
- }
-
- /**
- * @since 2.0
- */
- public InternalCDOView getView()
- {
- return view;
- }
-
- /**
- * @since 2.0
- */
- public void setContainer(InternalEObject eObject, CDOResource newResource, InternalEObject newEContainer,
- int newContainerFeatureID)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("setContainer({0}, {1}, {2}, {3})", cdoObject, newResource, newEContainer, newContainerFeatureID); //$NON-NLS-1$
- }
-
- Object newContainerID = newEContainer == null ? CDOID.NULL : cdoObject.cdoView().convertObjectToID(newEContainer,
- true);
- CDOID newResourceID = newResource == null ? CDOID.NULL : newResource.cdoID();
-
- CDOFeatureDelta delta = new CDOContainerFeatureDeltaImpl(newResourceID, newContainerID, newContainerFeatureID);
- InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
- revision.setResourceID(newResourceID);
- revision.setContainerID(newContainerID);
- revision.setContainingFeatureID(newContainerFeatureID);
- }
- }
-
- public InternalEObject getContainer(InternalEObject eObject)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("getContainer({0})", cdoObject); //$NON-NLS-1$
- }
-
- InternalCDORevision revision = getRevisionForReading(cdoObject);
- return (InternalEObject)convertIDToObject(cdoObject.cdoView(), cdoObject,
- EcorePackage.eINSTANCE.eContainingFeature(), -1, revision.getContainerID());
- }
- }
-
- public int getContainingFeatureID(InternalEObject eObject)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("getContainingFeatureID({0})", cdoObject); //$NON-NLS-1$
- }
-
- InternalCDORevision revision = getRevisionForReading(cdoObject);
- return revision.getContainingFeatureID();
- }
- }
-
- /**
- * @since 2.0
- */
- public InternalEObject getResource(InternalEObject eObject)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("getResource({0})", cdoObject); //$NON-NLS-1$
- }
-
- InternalCDORevision revision = getRevisionForReading(cdoObject);
- return (InternalEObject)convertIDToObject(cdoObject.cdoView(), cdoObject,
- EcorePackage.eINSTANCE.eContainingFeature(), -1, revision.getResourceID());
- }
- }
-
- public EStructuralFeature getContainingFeature(InternalEObject eObject)
- {
- throw new UnsupportedOperationException("Use getContainingFeatureID() instead"); //$NON-NLS-1$
- }
-
- public Object get(InternalEObject eObject, EStructuralFeature feature, int index)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("get({0}, {1}, {2})", cdoObject, feature, index); //$NON-NLS-1$
- }
-
- CDOFeatureAnalyzer featureAnalyzer = view.options().getFeatureAnalyzer();
-
- featureAnalyzer.preTraverseFeature(cdoObject, feature, index);
- InternalCDORevision revision = getRevisionForReading(cdoObject);
-
- Object value = revision.get(feature, index);
- value = convertToEMF(eObject, revision, feature, index, value);
-
- featureAnalyzer.postTraverseFeature(cdoObject, feature, index, value);
- return value;
- }
- }
-
- public boolean isSet(InternalEObject eObject, EStructuralFeature feature)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("isSet({0}, {1})", cdoObject, feature); //$NON-NLS-1$
- }
-
- if (!feature.isUnsettable())
- {
- if (feature.isMany())
- {
- InternalCDORevision revision = getRevisionForReading(cdoObject);
- CDOList list = revision.getList(feature);
- return list != null && !list.isEmpty();
- }
-
- Object value = eObject.eGet(feature);
- Object defaultValue = feature.getDefaultValue();
- return !ObjectUtil.equals(value, defaultValue);
- }
-
- // TODO This get() may not work for lists, see above
- Object value = get(eObject, feature, NO_INDEX);
- return value != null;
- }
- }
-
- public int size(InternalEObject eObject, EStructuralFeature feature)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("size({0}, {1})", cdoObject, feature); //$NON-NLS-1$
- }
-
- InternalCDORevision revision = getRevisionForReading(cdoObject);
- return revision.size(feature);
- }
- }
-
- public boolean isEmpty(InternalEObject eObject, EStructuralFeature feature)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("isEmpty({0}, {1})", cdoObject, feature); //$NON-NLS-1$
- }
-
- InternalCDORevision revision = getRevisionForReading(cdoObject);
- return revision.isEmpty(feature);
- }
- }
-
- public boolean contains(InternalEObject eObject, EStructuralFeature feature, Object value)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("contains({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$
- }
-
- Object convertedValue = convertToCDO(cdoObject, feature, value);
-
- InternalCDORevision revision = getRevisionForReading(cdoObject);
- boolean result = revision.contains(feature, convertedValue);
-
- // Special handling of detached (TRANSIENT) objects, see bug 354395
- if (!result && value != convertedValue && value instanceof EObject)
- {
- result = revision.contains(feature, value);
- }
-
- return result;
- }
- }
-
- public int indexOf(InternalEObject eObject, EStructuralFeature feature, Object value)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("indexOf({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$
- }
-
- value = convertToCDO(cdoObject, feature, value);
-
- InternalCDORevision revision = getRevisionForReading(cdoObject);
- return revision.indexOf(feature, value);
- }
- }
-
- public int lastIndexOf(InternalEObject eObject, EStructuralFeature feature, Object value)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("lastIndexOf({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$
- }
-
- value = convertToCDO(cdoObject, feature, value);
-
- InternalCDORevision revision = getRevisionForReading(cdoObject);
- return revision.lastIndexOf(feature, value);
- }
- }
-
- public int hashCode(InternalEObject eObject, EStructuralFeature feature)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("hashCode({0}, {1})", cdoObject, feature); //$NON-NLS-1$
- }
-
- InternalCDORevision revision = getRevisionForReading(cdoObject);
- return revision.hashCode(feature);
- }
- }
-
- public Object[] toArray(InternalEObject eObject, EStructuralFeature feature)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("toArray({0}, {1})", cdoObject, feature); //$NON-NLS-1$
- }
-
- InternalCDORevision revision = getRevisionForReading(cdoObject);
- Object[] result = revision.toArray(feature);
- for (int i = 0; i < result.length; i++)
- {
- result[i] = convertToEMF(eObject, revision, feature, i, result[i]);
- }
-
- // // TODO Clarify feature maps
- // if (feature instanceof EReference)
- // {
- // for (int i = 0; i < result.length; i++)
- // {
- // result[i] = resolveProxy(revision, feature, i, result[i]);
- // result[i] = convertIdToObject(cdoObject.cdoView(), eObject, feature, i, result[i]);
- // }
- // }
-
- return result;
- }
- }
-
- @SuppressWarnings("unchecked")
- public <T> T[] toArray(InternalEObject eObject, EStructuralFeature feature, T[] a)
- {
- synchronized (view)
- {
- Object[] array = toArray(eObject, feature);
- int size = array.length;
-
- if (a.length < size)
- {
- a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
- }
-
- System.arraycopy(array, 0, a, 0, size);
- if (a.length > size)
- {
- a[size] = null;
- }
-
- return a;
- }
- }
-
- public Object set(InternalEObject eObject, EStructuralFeature feature, int index, Object value)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("set({0}, {1}, {2}, {3})", cdoObject, feature, index, value); //$NON-NLS-1$
- }
-
- value = convertToCDO(cdoObject, feature, value);
-
- InternalCDORevision oldRevision = getRevisionForReading(cdoObject);
- Object oldValue = oldRevision.get(feature, index);
- oldValue = convertToEMF(eObject, oldRevision, feature, index, oldValue);
-
- CDOFeatureDelta delta = new CDOSetFeatureDeltaImpl(feature, index, value, oldValue);
- InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
- revision.set(feature, index, value);
-
- return oldValue;
- }
- }
-
- public void unset(InternalEObject eObject, EStructuralFeature feature)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("unset({0}, {1})", cdoObject, feature); //$NON-NLS-1$
- }
-
- CDOFeatureDelta delta = new CDOUnsetFeatureDeltaImpl(feature);
- InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
-
- if (feature.isUnsettable())
- {
- revision.unset(feature);
- }
- else
- {
- if (feature.isMany())
- {
- Object value = revision.getValue(feature);
-
- @SuppressWarnings("unchecked")
- List<Object> list = (List<Object>)value;
- list.clear();
- }
- else
- {
- Object defaultValue = convertToCDO(cdoObject, feature, feature.getDefaultValue());
- revision.set(feature, NO_INDEX, defaultValue);
- }
- }
- }
- }
-
- public void add(InternalEObject eObject, EStructuralFeature feature, int index, Object value)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("add({0}, {1}, {2}, {3})", cdoObject, feature, index, value); //$NON-NLS-1$
- }
-
- if (feature.isMany())
- {
- value = convertToCDO(cdoObject, feature, value);
- }
- else
- {
- throw new UnsupportedOperationException("ADD is not supported for single-valued features");
- }
-
- CDOFeatureDelta delta = new CDOAddFeatureDeltaImpl(feature, index, value);
- InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
- revision.add(feature, index, value);
- }
- }
-
- public Object remove(InternalEObject eObject, EStructuralFeature feature, int index)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("remove({0}, {1}, {2})", cdoObject, feature, index); //$NON-NLS-1$
- }
-
- Object oldValue = null;
-
- // Bugzilla 293283 / 314387
- if (feature.isMany())
- {
- InternalCDORevision readLockedRevision = getRevisionForReading(cdoObject);
- CDOList list = readLockedRevision.getList(feature);
- int size = list.size();
- if (index < 0 || size <= index)
- {
- throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
- }
- }
- else
- {
- throw new UnsupportedOperationException("REMOVE is not supported for single-valued features");
- }
-
- CDOFeatureDelta delta = new CDORemoveFeatureDeltaImpl(feature, index);
- InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
-
- oldValue = revision.remove(feature, index);
- return convertToEMF(eObject, revision, feature, index, oldValue);
- }
- }
-
- public void clear(InternalEObject eObject, EStructuralFeature feature)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("clear({0}, {1})", cdoObject, feature); //$NON-NLS-1$
- }
-
- CDOFeatureDelta delta = new CDOClearFeatureDeltaImpl(feature);
- InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
- // TODO Handle containment remove!!!
- revision.clear(feature);
- }
- }
-
- public Object move(InternalEObject eObject, EStructuralFeature feature, int target, int source)
- {
- synchronized (view)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject);
- if (TRACER.isEnabled())
- {
- TRACER.format("move({0}, {1}, {2}, {3})", cdoObject, feature, target, source); //$NON-NLS-1$
- }
-
- CDOFeatureDelta delta = new CDOMoveFeatureDeltaImpl(feature, target, source);
- InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
- Object result = revision.move(feature, target, source);
-
- result = convertToEMF(eObject, revision, feature, EStore.NO_INDEX, result);
- return result;
- }
- }
-
- public EObject create(EClass eClass)
- {
- throw new UnsupportedOperationException("Use the generated factory to create objects"); //$NON-NLS-1$
- }
-
- @Override
- public String toString()
- {
- return MessageFormat.format("CDOStore[{0}]", view); //$NON-NLS-1$
- }
-
- /**
- * @since 2.0
- */
- public Object resolveProxy(InternalCDORevision revision, EStructuralFeature feature, int index, Object value)
- {
- synchronized (view)
- {
- if (value instanceof CDOElementProxy)
- {
- // Resolve proxy
- CDOElementProxy proxy = (CDOElementProxy)value;
- value = view.getSession().resolveElementProxy(revision, feature, index, proxy.getIndex());
- }
-
- return value;
- }
- }
-
- /**
- * @since 3.0
- */
- public Object convertToCDO(InternalCDOObject object, EStructuralFeature feature, Object value)
- {
- synchronized (view)
- {
- if (value != null)
- {
- if (feature instanceof EReference)
- {
- value = view.convertObjectToID(value, true);
- }
- else if (FeatureMapUtil.isFeatureMap(feature))
- {
- FeatureMap.Entry entry = (FeatureMap.Entry)value;
- EStructuralFeature innerFeature = entry.getEStructuralFeature();
- Object innerValue = entry.getValue();
- Object convertedValue = view.convertObjectToID(innerValue);
- if (convertedValue != innerValue)
- {
- value = CDORevisionUtil.createFeatureMapEntry(innerFeature, convertedValue);
- }
- }
- else
- {
- CDOType type = CDOModelUtil.getType(feature.getEType());
- if (type != null)
- {
- value = type.convertToCDO(feature.getEType(), value);
- }
- }
- }
-
- return value;
- }
- }
-
- /**
- * @since 2.0
- */
- public Object convertToEMF(EObject eObject, InternalCDORevision revision, EStructuralFeature feature, int index,
- Object value)
- {
- synchronized (view)
- {
- if (value != null)
- {
- if (feature.isMany() && index != EStore.NO_INDEX)
- {
- value = resolveProxy(revision, feature, index, value);
- if (value instanceof CDOID)
- {
- CDOID id = (CDOID)value;
- CDOList list = revision.getList(feature);
- CDORevisionPrefetchingPolicy policy = view.options().getRevisionPrefetchingPolicy();
- InternalCDORevisionManager revisionManager = view.getSession().getRevisionManager();
- List<CDOID> listOfIDs = policy.loadAhead(revisionManager, view, eObject, feature, list, index, id);
- if (!listOfIDs.isEmpty())
- {
- int initialChunkSize = view.getSession().options().getCollectionLoadingPolicy().getInitialChunkSize();
- revisionManager.getRevisions(listOfIDs, view, initialChunkSize, CDORevision.DEPTH_NONE, true);
- }
- }
- }
-
- if (feature instanceof EReference)
- {
- value = convertIDToObject(view, eObject, feature, index, value);
- }
- else if (FeatureMapUtil.isFeatureMap(feature))
- {
- FeatureMap.Entry entry = (FeatureMap.Entry)value;
- EStructuralFeature innerFeature = entry.getEStructuralFeature();
- Object innerValue = entry.getValue();
- Object convertedValue = convertIDToObject(view, eObject, feature, index, innerValue);
- if (convertedValue != innerValue)
- {
- value = FeatureMapUtil.createEntry(innerFeature, convertedValue);
- }
- }
- else
- {
- CDOType type = CDOModelUtil.getType(feature.getEType());
- if (type != null)
- {
- value = type.convertToEMF(feature.getEType(), value);
- }
- }
- }
-
- return value;
- }
- }
-
- private Object convertIDToObject(InternalCDOView view, EObject eObject, EStructuralFeature feature, int index,
- Object value)
- {
- try
- {
- value = view.convertIDToObject(value);
- }
- catch (ObjectNotFoundException ex)
- {
- if (value instanceof CDOID)
- {
- value = view.options().getStaleReferencePolicy().processStaleReference(eObject, feature, index, ex.getID());
- }
- }
-
- return value;
- }
-
- private InternalCDOObject getCDOObject(Object object)
- {
- return FSMUtil.adapt(object, view);
- }
-
- private static InternalCDORevision getRevisionForReading(InternalCDOObject cdoObject)
- {
- CDOStateMachine.INSTANCE.read(cdoObject);
- return getRevision(cdoObject);
- }
-
- private static InternalCDORevision getRevisionForWriting(InternalCDOObject cdoObject, CDOFeatureDelta delta)
- {
- CDOStateMachine.INSTANCE.write(cdoObject, delta);
- return getRevision(cdoObject);
- }
-
- private static InternalCDORevision getRevision(InternalCDOObject cdoObject)
- {
- InternalCDORevision revision = cdoObject.cdoRevision();
- if (revision == null)
- {
- throw new IllegalStateException("revision == null");
- }
-
- return revision;
- }
-}
+/*
+ * Copyright (c) 2004 - 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
+ * Simon McDuff - bug 201266
+ * Eike Stepper & Simon McDuff - bug 204890
+ * Simon McDuff - bug 246705
+ * Simon McDuff - bug 246622
+ */
+package org.eclipse.emf.internal.cdo.view;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.CDOType;
+import org.eclipse.emf.cdo.common.revision.CDOElementProxy;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOAddFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOClearFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOContainerFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOMoveFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDORemoveFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOSetFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOUnsetFeatureDeltaImpl;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.util.ObjectNotFoundException;
+import org.eclipse.emf.cdo.view.CDOFeatureAnalyzer;
+import org.eclipse.emf.cdo.view.CDORevisionPrefetchingPolicy;
+
+import org.eclipse.emf.internal.cdo.bundle.OM;
+
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.InternalEObject.EStore;
+import org.eclipse.emf.ecore.util.FeatureMap;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+import org.eclipse.emf.spi.cdo.CDOStore;
+import org.eclipse.emf.spi.cdo.FSMUtil;
+import org.eclipse.emf.spi.cdo.InternalCDOObject;
+import org.eclipse.emf.spi.cdo.InternalCDOView;
+
+import java.text.MessageFormat;
+import java.util.List;
+
+/**
+ * CDORevision needs to follow these rules:<br>
+ * - Keep CDOID only when the object (!isNew && !isTransient) // Only when CDOID will not changed.<br>
+ * - Keep EObject for external reference, new, transient and that until commit time.<br>
+ * It is important since these objects could changed and we need to keep a reference to {@link EObject} until the end.
+ * It is the reason why {@link CDOStoreImpl} always call {@link InternalCDOView#convertObjectToID(Object, boolean)} with
+ * true.
+ *
+ * @author Eike Stepper
+ */
+public final class CDOStoreImpl implements CDOStore
+{
+ private final ContextTracer TRACER = new ContextTracer(OM.DEBUG_STORE, CDOStoreImpl.class);
+
+ private InternalCDOView view;
+
+ /**
+ * @since 2.0
+ */
+ public CDOStoreImpl(InternalCDOView view)
+ {
+ this.view = view;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public InternalCDOView getView()
+ {
+ return view;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void setContainer(InternalEObject eObject, CDOResource newResource, InternalEObject newEContainer,
+ int newContainerFeatureID)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("setContainer({0}, {1}, {2}, {3})", cdoObject, newResource, newEContainer, newContainerFeatureID); //$NON-NLS-1$
+ }
+
+ Object newContainerID = newEContainer == null ? CDOID.NULL : cdoObject.cdoView().convertObjectToID(newEContainer,
+ true);
+ CDOID newResourceID = newResource == null ? CDOID.NULL : newResource.cdoID();
+
+ CDOFeatureDelta delta = new CDOContainerFeatureDeltaImpl(newResourceID, newContainerID, newContainerFeatureID);
+ InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
+ revision.setResourceID(newResourceID);
+ revision.setContainerID(newContainerID);
+ revision.setContainingFeatureID(newContainerFeatureID);
+ }
+ }
+
+ public InternalEObject getContainer(InternalEObject eObject)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("getContainer({0})", cdoObject); //$NON-NLS-1$
+ }
+
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+ return (InternalEObject)convertIDToObject(cdoObject.cdoView(), cdoObject,
+ EcorePackage.eINSTANCE.eContainingFeature(), -1, revision.getContainerID());
+ }
+ }
+
+ public int getContainingFeatureID(InternalEObject eObject)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("getContainingFeatureID({0})", cdoObject); //$NON-NLS-1$
+ }
+
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+ return revision.getContainingFeatureID();
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public InternalEObject getResource(InternalEObject eObject)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("getResource({0})", cdoObject); //$NON-NLS-1$
+ }
+
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+ return (InternalEObject)convertIDToObject(cdoObject.cdoView(), cdoObject,
+ EcorePackage.eINSTANCE.eContainingFeature(), -1, revision.getResourceID());
+ }
+ }
+
+ public EStructuralFeature getContainingFeature(InternalEObject eObject)
+ {
+ throw new UnsupportedOperationException("Use getContainingFeatureID() instead"); //$NON-NLS-1$
+ }
+
+ public Object get(InternalEObject eObject, EStructuralFeature feature, int index)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("get({0}, {1}, {2})", cdoObject, feature, index); //$NON-NLS-1$
+ }
+
+ CDOFeatureAnalyzer featureAnalyzer = view.options().getFeatureAnalyzer();
+
+ featureAnalyzer.preTraverseFeature(cdoObject, feature, index);
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+
+ Object value = revision.get(feature, index);
+ value = convertToEMF(eObject, revision, feature, index, value);
+
+ featureAnalyzer.postTraverseFeature(cdoObject, feature, index, value);
+ return value;
+ }
+ }
+
+ public boolean isSet(InternalEObject eObject, EStructuralFeature feature)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("isSet({0}, {1})", cdoObject, feature); //$NON-NLS-1$
+ }
+
+ if (!feature.isUnsettable())
+ {
+ if (feature.isMany())
+ {
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+ CDOList list = revision.getList(feature);
+ return list != null && !list.isEmpty();
+ }
+
+ Object value = eObject.eGet(feature);
+ Object defaultValue = feature.getDefaultValue();
+ return !ObjectUtil.equals(value, defaultValue);
+ }
+
+ // TODO This get() may not work for lists, see above
+ Object value = get(eObject, feature, NO_INDEX);
+ return value != null;
+ }
+ }
+
+ public int size(InternalEObject eObject, EStructuralFeature feature)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("size({0}, {1})", cdoObject, feature); //$NON-NLS-1$
+ }
+
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+ return revision.size(feature);
+ }
+ }
+
+ public boolean isEmpty(InternalEObject eObject, EStructuralFeature feature)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("isEmpty({0}, {1})", cdoObject, feature); //$NON-NLS-1$
+ }
+
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+ return revision.isEmpty(feature);
+ }
+ }
+
+ public boolean contains(InternalEObject eObject, EStructuralFeature feature, Object value)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("contains({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$
+ }
+
+ Object convertedValue = convertToCDO(cdoObject, feature, value);
+
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+ boolean result = revision.contains(feature, convertedValue);
+
+ // Special handling of detached (TRANSIENT) objects, see bug 354395
+ if (!result && value != convertedValue && value instanceof EObject)
+ {
+ result = revision.contains(feature, value);
+ }
+
+ return result;
+ }
+ }
+
+ public int indexOf(InternalEObject eObject, EStructuralFeature feature, Object value)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("indexOf({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$
+ }
+
+ value = convertToCDO(cdoObject, feature, value);
+
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+ return revision.indexOf(feature, value);
+ }
+ }
+
+ public int lastIndexOf(InternalEObject eObject, EStructuralFeature feature, Object value)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("lastIndexOf({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$
+ }
+
+ value = convertToCDO(cdoObject, feature, value);
+
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+ return revision.lastIndexOf(feature, value);
+ }
+ }
+
+ public int hashCode(InternalEObject eObject, EStructuralFeature feature)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("hashCode({0}, {1})", cdoObject, feature); //$NON-NLS-1$
+ }
+
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+ return revision.hashCode(feature);
+ }
+ }
+
+ public Object[] toArray(InternalEObject eObject, EStructuralFeature feature)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("toArray({0}, {1})", cdoObject, feature); //$NON-NLS-1$
+ }
+
+ InternalCDORevision revision = getRevisionForReading(cdoObject);
+ Object[] result = revision.toArray(feature);
+ for (int i = 0; i < result.length; i++)
+ {
+ result[i] = convertToEMF(eObject, revision, feature, i, result[i]);
+ }
+
+ // // TODO Clarify feature maps
+ // if (feature instanceof EReference)
+ // {
+ // for (int i = 0; i < result.length; i++)
+ // {
+ // result[i] = resolveProxy(revision, feature, i, result[i]);
+ // result[i] = convertIdToObject(cdoObject.cdoView(), eObject, feature, i, result[i]);
+ // }
+ // }
+
+ return result;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T[] toArray(InternalEObject eObject, EStructuralFeature feature, T[] a)
+ {
+ synchronized (view)
+ {
+ Object[] array = toArray(eObject, feature);
+ int size = array.length;
+
+ if (a.length < size)
+ {
+ a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
+ }
+
+ System.arraycopy(array, 0, a, 0, size);
+ if (a.length > size)
+ {
+ a[size] = null;
+ }
+
+ return a;
+ }
+ }
+
+ public Object set(InternalEObject eObject, EStructuralFeature feature, int index, Object value)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("set({0}, {1}, {2}, {3})", cdoObject, feature, index, value); //$NON-NLS-1$
+ }
+
+ value = convertToCDO(cdoObject, feature, value);
+
+ InternalCDORevision oldRevision = getRevisionForReading(cdoObject);
+ Object oldValue = oldRevision.get(feature, index);
+ oldValue = convertToEMF(eObject, oldRevision, feature, index, oldValue);
+
+ CDOFeatureDelta delta = new CDOSetFeatureDeltaImpl(feature, index, value, oldValue);
+ InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
+ revision.set(feature, index, value);
+
+ return oldValue;
+ }
+ }
+
+ public void unset(InternalEObject eObject, EStructuralFeature feature)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("unset({0}, {1})", cdoObject, feature); //$NON-NLS-1$
+ }
+
+ CDOFeatureDelta delta = new CDOUnsetFeatureDeltaImpl(feature);
+ InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
+
+ if (feature.isUnsettable())
+ {
+ revision.unset(feature);
+ }
+ else
+ {
+ if (feature.isMany())
+ {
+ Object value = revision.getValue(feature);
+
+ @SuppressWarnings("unchecked")
+ List<Object> list = (List<Object>)value;
+ list.clear();
+ }
+ else
+ {
+ Object defaultValue = convertToCDO(cdoObject, feature, feature.getDefaultValue());
+ revision.set(feature, NO_INDEX, defaultValue);
+ }
+ }
+ }
+ }
+
+ public void add(InternalEObject eObject, EStructuralFeature feature, int index, Object value)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("add({0}, {1}, {2}, {3})", cdoObject, feature, index, value); //$NON-NLS-1$
+ }
+
+ if (feature.isMany())
+ {
+ value = convertToCDO(cdoObject, feature, value);
+ }
+ else
+ {
+ throw new UnsupportedOperationException("ADD is not supported for single-valued features");
+ }
+
+ CDOFeatureDelta delta = new CDOAddFeatureDeltaImpl(feature, index, value);
+ InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
+ revision.add(feature, index, value);
+ }
+ }
+
+ public Object remove(InternalEObject eObject, EStructuralFeature feature, int index)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("remove({0}, {1}, {2})", cdoObject, feature, index); //$NON-NLS-1$
+ }
+
+ Object oldValue = null;
+
+ // Bugzilla 293283 / 314387
+ if (feature.isMany())
+ {
+ InternalCDORevision readLockedRevision = getRevisionForReading(cdoObject);
+ CDOList list = readLockedRevision.getList(feature);
+ int size = list.size();
+ if (index < 0 || size <= index)
+ {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+ }
+ }
+ else
+ {
+ throw new UnsupportedOperationException("REMOVE is not supported for single-valued features");
+ }
+
+ CDOFeatureDelta delta = new CDORemoveFeatureDeltaImpl(feature, index);
+ InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
+
+ oldValue = revision.remove(feature, index);
+ return convertToEMF(eObject, revision, feature, index, oldValue);
+ }
+ }
+
+ public void clear(InternalEObject eObject, EStructuralFeature feature)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("clear({0}, {1})", cdoObject, feature); //$NON-NLS-1$
+ }
+
+ CDOFeatureDelta delta = new CDOClearFeatureDeltaImpl(feature);
+ InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
+ // TODO Handle containment remove!!!
+ revision.clear(feature);
+ }
+ }
+
+ public Object move(InternalEObject eObject, EStructuralFeature feature, int target, int source)
+ {
+ synchronized (view)
+ {
+ InternalCDOObject cdoObject = getCDOObject(eObject);
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("move({0}, {1}, {2}, {3})", cdoObject, feature, target, source); //$NON-NLS-1$
+ }
+
+ CDOFeatureDelta delta = new CDOMoveFeatureDeltaImpl(feature, target, source);
+ InternalCDORevision revision = getRevisionForWriting(cdoObject, delta);
+ Object result = revision.move(feature, target, source);
+
+ result = convertToEMF(eObject, revision, feature, EStore.NO_INDEX, result);
+ return result;
+ }
+ }
+
+ public EObject create(EClass eClass)
+ {
+ throw new UnsupportedOperationException("Use the generated factory to create objects"); //$NON-NLS-1$
+ }
+
+ @Override
+ public String toString()
+ {
+ return MessageFormat.format("CDOStore[{0}]", view); //$NON-NLS-1$
+ }
+
+ /**
+ * @since 2.0
+ */
+ public Object resolveProxy(InternalCDORevision revision, EStructuralFeature feature, int index, Object value)
+ {
+ synchronized (view)
+ {
+ if (value instanceof CDOElementProxy)
+ {
+ // Resolve proxy
+ CDOElementProxy proxy = (CDOElementProxy)value;
+ value = view.getSession().resolveElementProxy(revision, feature, index, proxy.getIndex());
+ }
+
+ return value;
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ public Object convertToCDO(InternalCDOObject object, EStructuralFeature feature, Object value)
+ {
+ synchronized (view)
+ {
+ if (value != null)
+ {
+ if (feature instanceof EReference)
+ {
+ value = view.convertObjectToID(value, true);
+ }
+ else if (FeatureMapUtil.isFeatureMap(feature))
+ {
+ FeatureMap.Entry entry = (FeatureMap.Entry)value;
+ EStructuralFeature innerFeature = entry.getEStructuralFeature();
+ Object innerValue = entry.getValue();
+ Object convertedValue = view.convertObjectToID(innerValue);
+ if (convertedValue != innerValue)
+ {
+ value = CDORevisionUtil.createFeatureMapEntry(innerFeature, convertedValue);
+ }
+ }
+ else
+ {
+ CDOType type = CDOModelUtil.getType(feature.getEType());
+ if (type != null)
+ {
+ value = type.convertToCDO(feature.getEType(), value);
+ }
+ }
+ }
+
+ return value;
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public Object convertToEMF(EObject eObject, InternalCDORevision revision, EStructuralFeature feature, int index,
+ Object value)
+ {
+ synchronized (view)
+ {
+ if (value != null)
+ {
+ if (feature.isMany())
+ {
+ if (index == EStore.NO_INDEX)
+ {
+ return value;
+ }
+
+ value = resolveProxy(revision, feature, index, value);
+ if (value instanceof CDOID)
+ {
+ CDOID id = (CDOID)value;
+ CDOList list = revision.getList(feature);
+ CDORevisionPrefetchingPolicy policy = view.options().getRevisionPrefetchingPolicy();
+ InternalCDORevisionManager revisionManager = view.getSession().getRevisionManager();
+ List<CDOID> listOfIDs = policy.loadAhead(revisionManager, view, eObject, feature, list, index, id);
+ if (!listOfIDs.isEmpty())
+ {
+ int initialChunkSize = view.getSession().options().getCollectionLoadingPolicy().getInitialChunkSize();
+ revisionManager.getRevisions(listOfIDs, view, initialChunkSize, CDORevision.DEPTH_NONE, true);
+ }
+ }
+ }
+
+ if (feature instanceof EReference)
+ {
+ value = convertIDToObject(view, eObject, feature, index, value);
+ }
+ else if (FeatureMapUtil.isFeatureMap(feature))
+ {
+ FeatureMap.Entry entry = (FeatureMap.Entry)value;
+ EStructuralFeature innerFeature = entry.getEStructuralFeature();
+ Object innerValue = entry.getValue();
+ Object convertedValue = convertIDToObject(view, eObject, feature, index, innerValue);
+ if (convertedValue != innerValue)
+ {
+ value = FeatureMapUtil.createEntry(innerFeature, convertedValue);
+ }
+ }
+ else
+ {
+ CDOType type = CDOModelUtil.getType(feature.getEType());
+ if (type != null)
+ {
+ value = type.convertToEMF(feature.getEType(), value);
+ }
+ }
+ }
+
+ return value;
+ }
+ }
+
+ private Object convertIDToObject(InternalCDOView view, EObject eObject, EStructuralFeature feature, int index,
+ Object value)
+ {
+ try
+ {
+ value = view.convertIDToObject(value);
+ }
+ catch (ObjectNotFoundException ex)
+ {
+ if (value instanceof CDOID)
+ {
+ value = view.options().getStaleReferencePolicy().processStaleReference(eObject, feature, index, ex.getID());
+ }
+ }
+
+ return value;
+ }
+
+ private InternalCDOObject getCDOObject(Object object)
+ {
+ return FSMUtil.adapt(object, view);
+ }
+
+ private static InternalCDORevision getRevisionForReading(InternalCDOObject cdoObject)
+ {
+ CDOStateMachine.INSTANCE.read(cdoObject);
+ return getRevision(cdoObject);
+ }
+
+ private static InternalCDORevision getRevisionForWriting(InternalCDOObject cdoObject, CDOFeatureDelta delta)
+ {
+ CDOStateMachine.INSTANCE.write(cdoObject, delta);
+ return getRevision(cdoObject);
+ }
+
+ private static InternalCDORevision getRevision(InternalCDOObject cdoObject)
+ {
+ InternalCDORevision revision = cdoObject.cdoRevision();
+ if (revision == null)
+ {
+ throw new IllegalStateException("revision == null");
+ }
+
+ return revision;
+ }
+}

Back to the top