diff options
author | Eike Stepper | 2012-05-01 17:04:16 +0000 |
---|---|---|
committer | Eike Stepper | 2012-05-01 17:04:16 +0000 |
commit | b3653fc883a10c28e1cb52da0bb31416c91b5ae3 (patch) | |
tree | 93b3ca22fb1d2ec271a6460485e60c1be59455e3 | |
parent | c621f5843cf8bc53f5ff7ec0ff2247ee279ef81d (diff) | |
download | cdo-b3653fc883a10c28e1cb52da0bb31416c91b5ae3.tar.gz cdo-b3653fc883a10c28e1cb52da0bb31416c91b5ae3.tar.xz cdo-b3653fc883a10c28e1cb52da0bb31416c91b5ae3.zip |
Revert "[369646] [DB] ClassCastException after setBranch when server cache contains partially loaded collections "
This reverts commit 5b576d6563e340f01b169e608f5e0596202a1230.
14 files changed, 7984 insertions, 8317 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java index a5265ea4b0..24124dcb4d 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java @@ -1,552 +1,553 @@ -/* - * 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 204890 - */ -package org.eclipse.emf.cdo.internal.common.revision.delta; - -import org.eclipse.emf.cdo.common.branch.CDOBranch; -import org.eclipse.emf.cdo.common.id.CDOID; -import org.eclipse.emf.cdo.common.id.CDOWithID; -import org.eclipse.emf.cdo.common.model.CDOModelUtil; -import org.eclipse.emf.cdo.common.protocol.CDODataInput; -import org.eclipse.emf.cdo.common.protocol.CDODataOutput; -import org.eclipse.emf.cdo.common.revision.CDOElementProxy; -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.CDORevisionData; -import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; -import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta; -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.CDOListFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta; -import org.eclipse.emf.cdo.common.util.PartialCollectionLoadingNotSupportedException; -import org.eclipse.emf.cdo.internal.common.revision.CDOListImpl; -import org.eclipse.emf.cdo.spi.common.revision.CDOReferenceAdjuster; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDOFeatureDelta; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta; - -import org.eclipse.emf.common.util.ECollections; -import org.eclipse.emf.common.util.EList; -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.change.ListChange; -import org.eclipse.emf.ecore.change.util.ListDifferenceAnalyzer; - -import java.io.IOException; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; - -/** - * @author Eike Stepper - */ -public class CDORevisionDeltaImpl implements InternalCDORevisionDelta -{ - private EClass eClass; - - private CDOID id; - - private CDOBranch branch; - - private int version; - - private CDORevisable target; - - private Map<EStructuralFeature, CDOFeatureDelta> featureDeltas = new HashMap<EStructuralFeature, CDOFeatureDelta>(); - - public CDORevisionDeltaImpl(CDORevision revision) - { - eClass = revision.getEClass(); - id = revision.getID(); - branch = revision.getBranch(); - version = revision.getVersion(); - } - - public CDORevisionDeltaImpl(CDORevisionDelta revisionDelta, boolean copyFeatureDeltas) - { - eClass = revisionDelta.getEClass(); - id = revisionDelta.getID(); - branch = revisionDelta.getBranch(); - version = revisionDelta.getVersion(); - - if (copyFeatureDeltas) - { - for (CDOFeatureDelta delta : revisionDelta.getFeatureDeltas()) - { - addFeatureDelta(((InternalCDOFeatureDelta)delta).copy()); - } - } - } - - public CDORevisionDeltaImpl(CDORevision sourceRevision, CDORevision targetRevision) - { - if (sourceRevision.getEClass() != targetRevision.getEClass()) - { - throw new IllegalArgumentException(); - } - - eClass = sourceRevision.getEClass(); - id = sourceRevision.getID(); - branch = sourceRevision.getBranch(); - version = sourceRevision.getVersion(); - target = CDORevisionUtil.copyRevisable(targetRevision); - - compare(sourceRevision, targetRevision); - - CDORevisionData originData = sourceRevision.data(); - CDORevisionData dirtyData = targetRevision.data(); - - Object dirtyContainerID = dirtyData.getContainerID(); - if (dirtyContainerID instanceof CDOWithID) - { - dirtyContainerID = ((CDOWithID)dirtyContainerID).cdoID(); - } - - if (!compare(originData.getContainerID(), dirtyContainerID) - || !compare(originData.getContainingFeatureID(), dirtyData.getContainingFeatureID()) - || !compare(originData.getResourceID(), dirtyData.getResourceID())) - { - addFeatureDelta(new CDOContainerFeatureDeltaImpl(dirtyData.getResourceID(), dirtyContainerID, - dirtyData.getContainingFeatureID())); - } - } - - public CDORevisionDeltaImpl(CDODataInput in) throws IOException - { - eClass = (EClass)in.readCDOClassifierRefAndResolve(); - id = in.readCDOID(); - branch = in.readCDOBranch(); - version = in.readInt(); - if (version < 0) - { - version = -version; - target = in.readCDORevisable(); - } - - int size = in.readInt(); - for (int i = 0; i < size; i++) - { - CDOFeatureDelta featureDelta = in.readCDOFeatureDelta(eClass); - featureDeltas.put(featureDelta.getFeature(), featureDelta); - } - } - - public void write(CDODataOutput out) throws IOException - { - out.writeCDOClassifierRef(eClass); - out.writeCDOID(id); - out.writeCDOBranch(branch); - if (target == null) - { - out.writeInt(version); - } - else - { - out.writeInt(-version); - out.writeCDORevisable(target); - } - - out.writeInt(featureDeltas.size()); - for (CDOFeatureDelta featureDelta : featureDeltas.values()) - { - out.writeCDOFeatureDelta(eClass, featureDelta); - } - } - - public EClass getEClass() - { - return eClass; - } - - public CDOID getID() - { - return id; - } - - public CDOBranch getBranch() - { - return branch; - } - - public void setBranch(CDOBranch branch) - { - this.branch = branch; - } - - public int getVersion() - { - return version; - } - - public void setVersion(int version) - { - this.version = version; - } - - public CDORevisable getTarget() - { - return target; - } - - public void setTarget(CDORevisable target) - { - this.target = target; - } - - public boolean isEmpty() - { - return featureDeltas.isEmpty(); - } - - public CDORevisionDelta copy() - { - return new CDORevisionDeltaImpl(this, true); - } - - public Map<EStructuralFeature, CDOFeatureDelta> getFeatureDeltaMap() - { - return featureDeltas; - } - - public CDOFeatureDelta getFeatureDelta(EStructuralFeature feature) - { - return featureDeltas.get(feature); - } - - public List<CDOFeatureDelta> getFeatureDeltas() - { - return new ArrayList<CDOFeatureDelta>(featureDeltas.values()); - } - - public void apply(CDORevision revision) - { - for (CDOFeatureDelta featureDelta : featureDeltas.values()) - { - ((CDOFeatureDeltaImpl)featureDelta).apply(revision); - } - } - - public void addFeatureDelta(CDOFeatureDelta delta) - { - if (delta instanceof CDOListFeatureDelta) - { - CDOListFeatureDelta deltas = (CDOListFeatureDelta)delta; - for (CDOFeatureDelta childDelta : deltas.getListChanges()) - { - addFeatureDelta(childDelta); - } - } - else - { - addSingleFeatureDelta(delta); - } - } - - private void addSingleFeatureDelta(CDOFeatureDelta delta) - { - EStructuralFeature feature = delta.getFeature(); - if (feature.isMany()) - { - CDOListFeatureDeltaImpl listDelta = (CDOListFeatureDeltaImpl)featureDeltas.get(feature); - if (listDelta == null) - { - listDelta = new CDOListFeatureDeltaImpl(feature); - featureDeltas.put(listDelta.getFeature(), listDelta); - } - - // Remove all previous changes - if (delta instanceof CDOClearFeatureDelta || delta instanceof CDOUnsetFeatureDelta) - { - listDelta.getListChanges().clear(); - } - - listDelta.add(delta); - } - else - { - featureDeltas.put(feature, delta); - } - } - - public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster) - { - boolean changed = false; - for (CDOFeatureDelta featureDelta : featureDeltas.values()) - { - changed |= ((CDOFeatureDeltaImpl)featureDelta).adjustReferences(referenceAdjuster); - } - - return changed; - } - - public void accept(CDOFeatureDeltaVisitor visitor) - { - for (CDOFeatureDelta featureDelta : featureDeltas.values()) - { - ((CDOFeatureDeltaImpl)featureDelta).accept(visitor); - } - } - - private void compare(CDORevision originRevision, CDORevision dirtyRevision) - { - CDORevisionData originData = originRevision.data(); - CDORevisionData dirtyData = dirtyRevision.data(); - - for (final EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass)) - { - if (feature.isMany()) - { - if (originData.size(feature) > 0 && dirtyData.size(feature) == 0) - { - addFeatureDelta(new CDOClearFeatureDeltaImpl(feature)); - } - else - { - CDOListFeatureDelta listFeatureDelta = new CDOListFeatureDeltaImpl(feature); - final List<CDOFeatureDelta> changes = listFeatureDelta.getListChanges(); - - ListDifferenceAnalyzer analyzer = new ListDifferenceAnalyzer() - { - @Override - public void analyzeLists(EList<Object> oldList, EList<?> newList, EList<ListChange> listChanges) - { - checkNoProxies(oldList); - checkNoProxies(newList); - super.analyzeLists(oldList, newList, listChanges); - } - - @Override - protected void createAddListChange(EList<Object> oldList, EList<ListChange> listChanges, Object value, - int index) - { - CDOFeatureDelta delta = new CDOAddFeatureDeltaImpl(feature, index, value); - changes.add(delta); - oldList.add(index, value); - } - - @Override - protected void createRemoveListChange(EList<?> oldList, EList<ListChange> listChanges, Object value, - int index) - { - CDORemoveFeatureDeltaImpl delta = new CDORemoveFeatureDeltaImpl(feature, index); - // fix until ListDifferenceAnalyzer delivers the correct value (bug #308618). - delta.setValue(oldList.get(index)); - changes.add(delta); - oldList.remove(index); - } - - @Override - protected void createMoveListChange(EList<?> oldList, EList<ListChange> listChanges, Object value, - int index, int toIndex) - { - CDOMoveFeatureDeltaImpl delta = new CDOMoveFeatureDeltaImpl(feature, toIndex, index); - // fix until ListDifferenceAnalyzer delivers the correct value (same problem as bug #308618). - delta.setValue(oldList.get(index)); - changes.add(delta); - oldList.move(toIndex, index); - } - - private void checkNoProxies(EList<?> list) - { - for (Object element : list) - { - if (element instanceof CDOElementProxy || element == CDOListImpl.UNINITIALIZED) - { - throw new PartialCollectionLoadingNotSupportedException("List contains proxy elements"); - } - } - } - }; - - CDOList originList = ((InternalCDORevision)originRevision).getList(feature); - CDOList dirtyList = ((InternalCDORevision)dirtyRevision).getList(feature); - - analyzer.analyzeLists(originList, dirtyList, new NOOPList()); - if (!changes.isEmpty()) - { - featureDeltas.put(feature, listFeatureDelta); - } - } - } - else - { - Object originValue = originData.get(feature, 0); - Object dirtyValue = dirtyData.get(feature, 0); - if (!compare(originValue, dirtyValue)) - { - if (dirtyValue == null) - { - addFeatureDelta(new CDOUnsetFeatureDeltaImpl(feature)); - } - else - { - addFeatureDelta(new CDOSetFeatureDeltaImpl(feature, 0, dirtyValue, originValue)); - } - } - } - } - } - - private boolean compare(Object originValue, Object dirtyValue) - { - return originValue == dirtyValue || originValue != null && dirtyValue != null && originValue.equals(dirtyValue); - } - - @Override - public String toString() - { - return MessageFormat.format("CDORevisionDelta[{0}@{1}:{2}v{3} --> {4}]", eClass.getName(), id, branch.getID(), - version, featureDeltas.values()); - } - - /** - * @author Eike Stepper - */ - public static class NOOPList implements EList<ListChange> - { - private static final EList<ListChange> LIST = ECollections.emptyEList(); - - public NOOPList() - { - } - - public int size() - { - return 0; - } - - public boolean isEmpty() - { - return true; - } - - public boolean contains(Object o) - { - return false; - } - - public Iterator<ListChange> iterator() - { - return LIST.iterator(); - } - - public Object[] toArray() - { - return LIST.toArray(); - } - - public <T> T[] toArray(T[] a) - { - return LIST.toArray(a); - } - - public boolean add(ListChange o) - { - return false; - } - - public boolean remove(Object o) - { - return false; - } - - public boolean containsAll(Collection<?> c) - { - return false; - } - - public boolean addAll(Collection<? extends ListChange> c) - { - return false; - } - - public boolean addAll(int index, Collection<? extends ListChange> c) - { - return false; - } - - public boolean removeAll(Collection<?> c) - { - return false; - } - - public boolean retainAll(Collection<?> c) - { - return false; - } - - public void clear() - { - } - - public ListChange get(int index) - { - return LIST.get(index); - } - - public ListChange set(int index, ListChange element) - { - return null; - } - - public void add(int index, ListChange element) - { - } - - public ListChange remove(int index) - { - return null; - } - - public int indexOf(Object o) - { - return LIST.indexOf(o); - } - - public int lastIndexOf(Object o) - { - return LIST.lastIndexOf(o); - } - - public ListIterator<ListChange> listIterator() - { - return LIST.listIterator(); - } - - public ListIterator<ListChange> listIterator(int index) - { - return LIST.listIterator(index); - } - - public List<ListChange> subList(int fromIndex, int toIndex) - { - return LIST.subList(fromIndex, toIndex); - } - - public void move(int newPosition, ListChange object) - { - } - - public ListChange move(int newPosition, int oldPosition) - { - return null; - } - } -} +/*
+ * 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 204890
+ */
+package org.eclipse.emf.cdo.internal.common.revision.delta;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOWithID;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDOElementProxy;
+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.CDORevisionData;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+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.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.common.util.PartialCollectionLoadingNotSupportedException;
+import org.eclipse.emf.cdo.internal.common.revision.CDOListImpl;
+import org.eclipse.emf.cdo.internal.common.revision.CDORevisionImpl;
+import org.eclipse.emf.cdo.spi.common.revision.CDOReferenceAdjuster;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDOFeatureDelta;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+
+import org.eclipse.emf.common.util.ECollections;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.change.ListChange;
+import org.eclipse.emf.ecore.change.util.ListDifferenceAnalyzer;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public class CDORevisionDeltaImpl implements InternalCDORevisionDelta
+{
+ private EClass eClass;
+
+ private CDOID id;
+
+ private CDOBranch branch;
+
+ private int version;
+
+ private CDORevisable target;
+
+ private Map<EStructuralFeature, CDOFeatureDelta> featureDeltas = new HashMap<EStructuralFeature, CDOFeatureDelta>();
+
+ public CDORevisionDeltaImpl(CDORevision revision)
+ {
+ eClass = revision.getEClass();
+ id = revision.getID();
+ branch = revision.getBranch();
+ version = revision.getVersion();
+ }
+
+ public CDORevisionDeltaImpl(CDORevisionDelta revisionDelta, boolean copyFeatureDeltas)
+ {
+ eClass = revisionDelta.getEClass();
+ id = revisionDelta.getID();
+ branch = revisionDelta.getBranch();
+ version = revisionDelta.getVersion();
+
+ if (copyFeatureDeltas)
+ {
+ for (CDOFeatureDelta delta : revisionDelta.getFeatureDeltas())
+ {
+ addFeatureDelta(((InternalCDOFeatureDelta)delta).copy());
+ }
+ }
+ }
+
+ public CDORevisionDeltaImpl(CDORevision sourceRevision, CDORevision targetRevision)
+ {
+ if (sourceRevision.getEClass() != targetRevision.getEClass())
+ {
+ throw new IllegalArgumentException();
+ }
+
+ eClass = sourceRevision.getEClass();
+ id = sourceRevision.getID();
+ branch = sourceRevision.getBranch();
+ version = sourceRevision.getVersion();
+ target = CDORevisionUtil.copyRevisable(targetRevision);
+
+ compare(sourceRevision, targetRevision);
+
+ CDORevisionData originData = sourceRevision.data();
+ CDORevisionData dirtyData = targetRevision.data();
+
+ Object dirtyContainerID = dirtyData.getContainerID();
+ if (dirtyContainerID instanceof CDOWithID)
+ {
+ dirtyContainerID = ((CDOWithID)dirtyContainerID).cdoID();
+ }
+
+ if (!compare(originData.getContainerID(), dirtyContainerID)
+ || !compare(originData.getContainingFeatureID(), dirtyData.getContainingFeatureID())
+ || !compare(originData.getResourceID(), dirtyData.getResourceID()))
+ {
+ addFeatureDelta(new CDOContainerFeatureDeltaImpl(dirtyData.getResourceID(), dirtyContainerID,
+ dirtyData.getContainingFeatureID()));
+ }
+ }
+
+ public CDORevisionDeltaImpl(CDODataInput in) throws IOException
+ {
+ eClass = (EClass)in.readCDOClassifierRefAndResolve();
+ id = in.readCDOID();
+ branch = in.readCDOBranch();
+ version = in.readInt();
+ if (version < 0)
+ {
+ version = -version;
+ target = in.readCDORevisable();
+ }
+
+ int size = in.readInt();
+ for (int i = 0; i < size; i++)
+ {
+ CDOFeatureDelta featureDelta = in.readCDOFeatureDelta(eClass);
+ featureDeltas.put(featureDelta.getFeature(), featureDelta);
+ }
+ }
+
+ public void write(CDODataOutput out) throws IOException
+ {
+ out.writeCDOClassifierRef(eClass);
+ out.writeCDOID(id);
+ out.writeCDOBranch(branch);
+ if (target == null)
+ {
+ out.writeInt(version);
+ }
+ else
+ {
+ out.writeInt(-version);
+ out.writeCDORevisable(target);
+ }
+
+ out.writeInt(featureDeltas.size());
+ for (CDOFeatureDelta featureDelta : featureDeltas.values())
+ {
+ out.writeCDOFeatureDelta(eClass, featureDelta);
+ }
+ }
+
+ public EClass getEClass()
+ {
+ return eClass;
+ }
+
+ public CDOID getID()
+ {
+ return id;
+ }
+
+ public CDOBranch getBranch()
+ {
+ return branch;
+ }
+
+ public void setBranch(CDOBranch branch)
+ {
+ this.branch = branch;
+ }
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(int version)
+ {
+ this.version = version;
+ }
+
+ public CDORevisable getTarget()
+ {
+ return target;
+ }
+
+ public void setTarget(CDORevisable target)
+ {
+ this.target = target;
+ }
+
+ public boolean isEmpty()
+ {
+ return featureDeltas.isEmpty();
+ }
+
+ public CDORevisionDelta copy()
+ {
+ return new CDORevisionDeltaImpl(this, true);
+ }
+
+ public Map<EStructuralFeature, CDOFeatureDelta> getFeatureDeltaMap()
+ {
+ return featureDeltas;
+ }
+
+ public CDOFeatureDelta getFeatureDelta(EStructuralFeature feature)
+ {
+ return featureDeltas.get(feature);
+ }
+
+ public List<CDOFeatureDelta> getFeatureDeltas()
+ {
+ return new ArrayList<CDOFeatureDelta>(featureDeltas.values());
+ }
+
+ public void apply(CDORevision revision)
+ {
+ for (CDOFeatureDelta featureDelta : featureDeltas.values())
+ {
+ ((CDOFeatureDeltaImpl)featureDelta).apply(revision);
+ }
+ }
+
+ public void addFeatureDelta(CDOFeatureDelta delta)
+ {
+ if (delta instanceof CDOListFeatureDelta)
+ {
+ CDOListFeatureDelta deltas = (CDOListFeatureDelta)delta;
+ for (CDOFeatureDelta childDelta : deltas.getListChanges())
+ {
+ addFeatureDelta(childDelta);
+ }
+ }
+ else
+ {
+ addSingleFeatureDelta(delta);
+ }
+ }
+
+ private void addSingleFeatureDelta(CDOFeatureDelta delta)
+ {
+ EStructuralFeature feature = delta.getFeature();
+ if (feature.isMany())
+ {
+ CDOListFeatureDeltaImpl listDelta = (CDOListFeatureDeltaImpl)featureDeltas.get(feature);
+ if (listDelta == null)
+ {
+ listDelta = new CDOListFeatureDeltaImpl(feature);
+ featureDeltas.put(listDelta.getFeature(), listDelta);
+ }
+
+ // Remove all previous changes
+ if (delta instanceof CDOClearFeatureDelta || delta instanceof CDOUnsetFeatureDelta)
+ {
+ listDelta.getListChanges().clear();
+ }
+
+ listDelta.add(delta);
+ }
+ else
+ {
+ featureDeltas.put(feature, delta);
+ }
+ }
+
+ public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster)
+ {
+ boolean changed = false;
+ for (CDOFeatureDelta featureDelta : featureDeltas.values())
+ {
+ changed |= ((CDOFeatureDeltaImpl)featureDelta).adjustReferences(referenceAdjuster);
+ }
+
+ return changed;
+ }
+
+ public void accept(CDOFeatureDeltaVisitor visitor)
+ {
+ for (CDOFeatureDelta featureDelta : featureDeltas.values())
+ {
+ ((CDOFeatureDeltaImpl)featureDelta).accept(visitor);
+ }
+ }
+
+ private void compare(CDORevision originRevision, CDORevision dirtyRevision)
+ {
+ CDORevisionData originData = originRevision.data();
+ CDORevisionData dirtyData = dirtyRevision.data();
+
+ for (final EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass))
+ {
+ if (feature.isMany())
+ {
+ if (originData.size(feature) > 0 && dirtyData.size(feature) == 0)
+ {
+ addFeatureDelta(new CDOClearFeatureDeltaImpl(feature));
+ }
+ else
+ {
+ CDOListFeatureDelta listFeatureDelta = new CDOListFeatureDeltaImpl(feature);
+ final List<CDOFeatureDelta> changes = listFeatureDelta.getListChanges();
+
+ ListDifferenceAnalyzer analyzer = new ListDifferenceAnalyzer()
+ {
+ @Override
+ public void analyzeLists(EList<Object> oldList, EList<?> newList, EList<ListChange> listChanges)
+ {
+ checkNoProxies(oldList);
+ checkNoProxies(newList);
+ super.analyzeLists(oldList, newList, listChanges);
+ }
+
+ @Override
+ protected void createAddListChange(EList<Object> oldList, EList<ListChange> listChanges, Object value,
+ int index)
+ {
+ CDOFeatureDelta delta = new CDOAddFeatureDeltaImpl(feature, index, value);
+ changes.add(delta);
+ oldList.add(index, value);
+ }
+
+ @Override
+ protected void createRemoveListChange(EList<?> oldList, EList<ListChange> listChanges, Object value,
+ int index)
+ {
+ CDORemoveFeatureDeltaImpl delta = new CDORemoveFeatureDeltaImpl(feature, index);
+ // fix until ListDifferenceAnalyzer delivers the correct value (bug #308618).
+ delta.setValue(oldList.get(index));
+ changes.add(delta);
+ oldList.remove(index);
+ }
+
+ @Override
+ protected void createMoveListChange(EList<?> oldList, EList<ListChange> listChanges, Object value,
+ int index, int toIndex)
+ {
+ CDOMoveFeatureDeltaImpl delta = new CDOMoveFeatureDeltaImpl(feature, toIndex, index);
+ // fix until ListDifferenceAnalyzer delivers the correct value (same problem as bug #308618).
+ delta.setValue(oldList.get(index));
+ changes.add(delta);
+ oldList.move(toIndex, index);
+ }
+
+ private void checkNoProxies(EList<?> list)
+ {
+ for (Object element : list)
+ {
+ if (element instanceof CDOElementProxy || element == CDOListImpl.UNINITIALIZED)
+ {
+ throw new PartialCollectionLoadingNotSupportedException("List contains proxy elements");
+ }
+ }
+ }
+ };
+
+ CDOList originList = ((InternalCDORevision)originRevision).getList(feature);
+ CDOList dirtyList = ((InternalCDORevision)dirtyRevision).getList(feature);
+
+ analyzer.analyzeLists(originList, dirtyList, new NOOPList());
+ if (!changes.isEmpty())
+ {
+ featureDeltas.put(feature, listFeatureDelta);
+ }
+ }
+ }
+ else
+ {
+ Object originValue = originData.get(feature, 0);
+ Object dirtyValue = dirtyData.get(feature, 0);
+ if (!compare(originValue, dirtyValue))
+ {
+ if (dirtyValue == null)
+ {
+ addFeatureDelta(new CDOUnsetFeatureDeltaImpl(feature));
+ }
+ else
+ {
+ addFeatureDelta(new CDOSetFeatureDeltaImpl(feature, 0, dirtyValue, originValue));
+ }
+ }
+ }
+ }
+ }
+
+ private boolean compare(Object originValue, Object dirtyValue)
+ {
+ return originValue == dirtyValue || originValue != null && dirtyValue != null && originValue.equals(dirtyValue);
+ }
+
+ @Override
+ public String toString()
+ {
+ return MessageFormat.format("CDORevisionDelta[{0}@{1}:{2}v{3} --> {4}]", eClass.getName(), id, branch.getID(),
+ version, featureDeltas.values());
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class NOOPList implements EList<ListChange>
+ {
+ private static final EList<ListChange> LIST = ECollections.emptyEList();
+
+ public NOOPList()
+ {
+ }
+
+ public int size()
+ {
+ return 0;
+ }
+
+ public boolean isEmpty()
+ {
+ return true;
+ }
+
+ public boolean contains(Object o)
+ {
+ return false;
+ }
+
+ public Iterator<ListChange> iterator()
+ {
+ return LIST.iterator();
+ }
+
+ public Object[] toArray()
+ {
+ return LIST.toArray();
+ }
+
+ public <T> T[] toArray(T[] a)
+ {
+ return LIST.toArray(a);
+ }
+
+ public boolean add(ListChange o)
+ {
+ return false;
+ }
+
+ public boolean remove(Object o)
+ {
+ return false;
+ }
+
+ public boolean containsAll(Collection<?> c)
+ {
+ return false;
+ }
+
+ public boolean addAll(Collection<? extends ListChange> c)
+ {
+ return false;
+ }
+
+ public boolean addAll(int index, Collection<? extends ListChange> c)
+ {
+ return false;
+ }
+
+ public boolean removeAll(Collection<?> c)
+ {
+ return false;
+ }
+
+ public boolean retainAll(Collection<?> c)
+ {
+ return false;
+ }
+
+ public void clear()
+ {
+ }
+
+ public ListChange get(int index)
+ {
+ return LIST.get(index);
+ }
+
+ public ListChange set(int index, ListChange element)
+ {
+ return null;
+ }
+
+ public void add(int index, ListChange element)
+ {
+ }
+
+ public ListChange remove(int index)
+ {
+ return null;
+ }
+
+ public int indexOf(Object o)
+ {
+ return LIST.indexOf(o);
+ }
+
+ public int lastIndexOf(Object o)
+ {
+ return LIST.lastIndexOf(o);
+ }
+
+ public ListIterator<ListChange> listIterator()
+ {
+ return LIST.listIterator();
+ }
+
+ public ListIterator<ListChange> listIterator(int index)
+ {
+ return LIST.listIterator(index);
+ }
+
+ public List<ListChange> subList(int fromIndex, int toIndex)
+ {
+ return LIST.subList(fromIndex, toIndex);
+ }
+
+ public void move(int newPosition, ListChange object)
+ {
+ }
+
+ public ListChange move(int newPosition, int oldPosition)
+ {
+ return null;
+ }
+ }
+}
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 7ad3215886..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 @@ -65,6 +65,7 @@ import java.util.Map; */ 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); @@ -77,11 +78,9 @@ public abstract class BaseCDORevision extends AbstractCDORevision private static final byte SET_NOT_NULL = 2; - private static final byte PERMISSION_MASK = 0x03; - private static final byte FROZEN_FLAG = 0x04; - private static final byte UNCHUNKED_FLAG = 0x08; + private static final byte PERMISSION_MASK = 0x03; private CDOID id; @@ -146,13 +145,13 @@ public abstract class BaseCDORevision extends AbstractCDORevision readSystemValues(in); - byte flagBits = (byte)(in.readByte() & ~FROZEN_FLAG); - if ((flagBits & PERMISSION_MASK) != CDOPermission.NONE.ordinal()) + byte permissionBits = (byte)(in.readByte() & PERMISSION_MASK); + if (permissionBits != CDOPermission.NONE.ordinal()) { readValues(in); } - flags = flagBits; + flags = permissionBits; if (READING.isEnabled()) { @@ -204,7 +203,7 @@ public abstract class BaseCDORevision extends AbstractCDORevision CDOPermissionProvider permissionProvider = out.getPermissionProvider(); CDOPermission permission = permissionProvider.getPermission(this); - out.writeByte(permission.getBits() | flags & UNCHUNKED_FLAG); + out.writeByte(permission.getBits()); if (permission != CDOPermission.NONE) { @@ -733,22 +732,6 @@ public abstract class BaseCDORevision extends AbstractCDORevision } } - /** - * @since 4.1 - */ - public boolean isUnchunked() - { - return (flags & UNCHUNKED_FLAG) != 0; - } - - /** - * @since 4.1 - */ - public void setUnchunked() - { - flags |= UNCHUNKED_FLAG; - } - protected Object getValue(int featureIndex) { checkReadable(); 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 f743b2bbb1..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 @@ -354,20 +354,4 @@ public abstract class DelegatingCDORevision implements InternalCDORevision { getDelegate().freeze(); } - - /** - * @since 4.1 - */ - public boolean isUnchunked() - { - return getDelegate().isUnchunked(); - } - - /** - * @since 4.1 - */ - public void setUnchunked() - { - getDelegate().setUnchunked(); - } } 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 985b397ec4..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 @@ -126,14 +126,4 @@ public interface InternalCDORevision extends CDORevision, CDORevisionData, CDORe * @since 4.0 */ public void freeze(); - - /** - * @since 4.1 - */ - public boolean isUnchunked(); - - /** - * @since 4.1 - */ - public void setUnchunked(); } 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 06d958dfd1..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 @@ -279,22 +279,6 @@ public class StubCDORevision extends AbstractCDORevision throw new UnsupportedOperationException(getExceptionMessage()); } - /** - * @since 4.1 - */ - public boolean isUnchunked() - { - throw new UnsupportedOperationException(getExceptionMessage()); - } - - /** - * @since 4.1 - */ - public void setUnchunked() - { - throw new UnsupportedOperationException(getExceptionMessage()); - } - private String getExceptionMessage() { return "Unsupported operation in " + this; diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java index b3b1ca7d79..2ac02db01c 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java @@ -1,1117 +1,1124 @@ -/* - * 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 - * Stefan Winkler - major refactoring - * Stefan Winkler - 249610: [DB] Support external references (Implementation) - * Stefan Winkler - derived branch mapping from audit mapping - * Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy - */ -package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal; - -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.id.CDOID; -import org.eclipse.emf.cdo.common.revision.CDOList; -import org.eclipse.emf.cdo.common.revision.CDORevision; -import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; -import org.eclipse.emf.cdo.common.revision.CDORevisionManager; -import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor; -import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta; -import org.eclipse.emf.cdo.eresource.EresourcePackage; -import org.eclipse.emf.cdo.server.IRepository; -import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext; -import org.eclipse.emf.cdo.server.db.IDBStoreAccessor; -import org.eclipse.emf.cdo.server.db.IIDHandler; -import org.eclipse.emf.cdo.server.db.IPreparedStatementCache; -import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability; -import org.eclipse.emf.cdo.server.db.mapping.IClassMappingAuditSupport; -import org.eclipse.emf.cdo.server.db.mapping.IClassMappingDeltaSupport; -import org.eclipse.emf.cdo.server.db.mapping.IListMapping; -import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport; -import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping; -import org.eclipse.emf.cdo.server.internal.db.CDODBSchema; -import org.eclipse.emf.cdo.server.internal.db.bundle.OM; -import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment; -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.server.InternalRepository; - -import org.eclipse.net4j.db.DBException; -import org.eclipse.net4j.db.DBType; -import org.eclipse.net4j.db.DBUtil; -import org.eclipse.net4j.db.ddl.IDBField; -import org.eclipse.net4j.db.ddl.IDBTable; -import org.eclipse.net4j.util.ImplementationError; -import org.eclipse.net4j.util.om.monitor.OMMonitor; -import org.eclipse.net4j.util.om.monitor.OMMonitor.Async; -import org.eclipse.net4j.util.om.trace.ContextTracer; - -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EStructuralFeature; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * @author Eike Stepper - * @author Stefan Winkler - * @since 3.0 - */ -public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapping implements - IClassMappingAuditSupport, IClassMappingDeltaSupport -{ - /** - * @author Stefan Winkler - */ - private class FeatureDeltaWriter implements CDOFeatureDeltaVisitor - { - private IDBStoreAccessor accessor; - - private long created; - - private CDOID id; - - private CDOBranch targetBranch; - - private int oldVersion; - - private int newVersion; - - private InternalCDORevision newRevision; - - public void process(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created) - { - this.accessor = accessor; - this.created = created; - id = delta.getID(); - oldVersion = delta.getVersion(); - - if (TRACER.isEnabled()) - { - TRACER.format("FeatureDeltaWriter: old version: {0}, new version: {1}", oldVersion, oldVersion + 1); //$NON-NLS-1$ - } - - InternalCDORevision originalRevision = (InternalCDORevision)accessor.getTransaction().getRevision(id); - newRevision = originalRevision.copy(); - targetBranch = accessor.getTransaction().getBranch(); - newRevision.adjustForCommit(targetBranch, created); - - newVersion = newRevision.getVersion(); - - // process revision delta tree - delta.accept(this); - - if (newVersion != CDORevision.FIRST_VERSION) - { - reviseOldRevision(accessor, id, delta.getBranch(), newRevision.getTimeStamp() - 1); - } - - writeValues(accessor, newRevision); - } - - public void visit(CDOMoveFeatureDelta delta) - { - throw new ImplementationError("Should not be called"); //$NON-NLS-1$ - } - - public void visit(CDOAddFeatureDelta delta) - { - throw new ImplementationError("Should not be called"); //$NON-NLS-1$ - } - - public void visit(CDORemoveFeatureDelta delta) - { - throw new ImplementationError("Should not be called"); //$NON-NLS-1$ - } - - public void visit(CDOSetFeatureDelta delta) - { - delta.apply(newRevision); - } - - public void visit(CDOUnsetFeatureDelta delta) - { - delta.apply(newRevision); - } - - public void visit(CDOListFeatureDelta delta) - { - delta.apply(newRevision); - IListMappingDeltaSupport listMapping = (IListMappingDeltaSupport)getListMapping(delta.getFeature()); - listMapping.processDelta(accessor, id, targetBranch.getID(), oldVersion, newVersion, created, delta); - } - - public void visit(CDOClearFeatureDelta delta) - { - throw new ImplementationError("Should not be called"); //$NON-NLS-1$ - } - - public void visit(CDOContainerFeatureDelta delta) - { - delta.apply(newRevision); - } - } - - private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, HorizontalBranchingClassMapping.class); - - private String sqlInsertAttributes; - - private String sqlSelectCurrentAttributes; - - private String sqlSelectAllObjectIDs; - - private String sqlSelectAttributesByTime; - - private String sqlSelectAttributesByVersion; - - private String sqlReviseAttributes; - - private String sqlSelectForHandle; - - private String sqlSelectForChangeSet; - - private ThreadLocal<FeatureDeltaWriter> deltaWriter = new ThreadLocal<FeatureDeltaWriter>() - { - @Override - protected FeatureDeltaWriter initialValue() - { - return new FeatureDeltaWriter(); - } - }; - - public HorizontalBranchingClassMapping(AbstractHorizontalMappingStrategy mappingStrategy, EClass eClass) - { - super(mappingStrategy, eClass); - - initSQLStrings(); - } - - @Override - protected IDBField addBranchingField(IDBTable table) - { - return table.addField(CDODBSchema.ATTRIBUTES_BRANCH, DBType.INTEGER, true); - } - - private void initSQLStrings() - { - Map<EStructuralFeature, String> unsettableFields = getUnsettableFields(); - Map<EStructuralFeature, String> listSizeFields = getListSizeFields(); - - // ----------- Select Revision --------------------------- - StringBuilder builder = new StringBuilder(); - - builder.append("SELECT "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_VERSION); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_CREATED); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_RESOURCE); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_CONTAINER); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_FEATURE); - - for (ITypeMapping singleMapping : getValueMappings()) - { - builder.append(", "); //$NON-NLS-1$ - builder.append(singleMapping.getField()); - } - - if (unsettableFields != null) - { - for (String fieldName : unsettableFields.values()) - { - builder.append(", "); //$NON-NLS-1$ - builder.append(fieldName); - } - } - - if (listSizeFields != null) - { - for (String fieldName : listSizeFields.values()) - { - builder.append(", "); //$NON-NLS-1$ - builder.append(fieldName); - } - } - - builder.append(" FROM "); //$NON-NLS-1$ - builder.append(getTable()); - builder.append(" WHERE "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_ID); - builder.append("=? AND "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_BRANCH); - builder.append("=? AND ("); //$NON-NLS-1$ - String sqlSelectAttributesPrefix = builder.toString(); - - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("=0)"); //$NON-NLS-1$ - - sqlSelectCurrentAttributes = builder.toString(); - - builder = new StringBuilder(sqlSelectAttributesPrefix); - - builder.append(CDODBSchema.ATTRIBUTES_CREATED); - builder.append("<=? AND ("); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("=0 OR "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append(">=?))"); //$NON-NLS-1$ - - sqlSelectAttributesByTime = builder.toString(); - - builder = new StringBuilder(sqlSelectAttributesPrefix); - - builder.append("ABS("); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_VERSION); - builder.append(")=?)"); //$NON-NLS-1$ - - sqlSelectAttributesByVersion = builder.toString(); - - // ----------- Insert Attributes ------------------------- - builder = new StringBuilder(); - builder.append("INSERT INTO "); //$NON-NLS-1$ - builder.append(getTable()); - - builder.append("("); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_ID); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_VERSION); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_BRANCH); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_CREATED); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_RESOURCE); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_CONTAINER); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_FEATURE); - - for (ITypeMapping singleMapping : getValueMappings()) - { - builder.append(", "); //$NON-NLS-1$ - builder.append(singleMapping.getField()); - } - - if (unsettableFields != null) - { - for (String fieldName : unsettableFields.values()) - { - builder.append(", "); //$NON-NLS-1$ - builder.append(fieldName); - } - } - - if (listSizeFields != null) - { - for (String fieldName : listSizeFields.values()) - { - builder.append(", "); //$NON-NLS-1$ - builder.append(fieldName); - } - } - - builder.append(") VALUES (?, ?, ?, ?, ?, ?, ?, ?"); //$NON-NLS-1$ - - for (int i = 0; i < getValueMappings().size(); i++) - { - builder.append(", ?"); //$NON-NLS-1$ - } - - if (unsettableFields != null) - { - for (int i = 0; i < unsettableFields.size(); i++) - { - builder.append(", ?"); //$NON-NLS-1$ - } - } - - if (listSizeFields != null) - { - for (int i = 0; i < listSizeFields.size(); i++) - { - builder.append(", ?"); //$NON-NLS-1$ - } - } - - builder.append(")"); //$NON-NLS-1$ - sqlInsertAttributes = builder.toString(); - - // ----------- Update to set revised ---------------- - builder = new StringBuilder("UPDATE "); //$NON-NLS-1$ - builder.append(getTable()); - builder.append(" SET "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("=? WHERE "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_ID); - builder.append("=? AND "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_BRANCH); - builder.append("=? AND "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("=0"); //$NON-NLS-1$ - sqlReviseAttributes = builder.toString(); - - // ----------- Select all unrevised Object IDs ------ - builder = new StringBuilder("SELECT "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_ID); - builder.append(" FROM "); //$NON-NLS-1$ - builder.append(getTable()); - builder.append(" WHERE "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("=0"); //$NON-NLS-1$ - sqlSelectAllObjectIDs = builder.toString(); - - // ----------- Select all revisions (for handleRevision) --- - builder = new StringBuilder("SELECT "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_ID); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_VERSION); - builder.append(", "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_BRANCH); - builder.append(" FROM "); //$NON-NLS-1$ - builder.append(getTable()); - sqlSelectForHandle = builder.toString(); - - // ----------- Select all revisions (for handleRevision) --- - builder = new StringBuilder("SELECT DISTINCT "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_ID); - builder.append(" FROM "); //$NON-NLS-1$ - builder.append(getTable()); - builder.append(" WHERE "); //$NON-NLS-1$ - sqlSelectForChangeSet = builder.toString(); - } - - public boolean readRevision(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk) - { - IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); - IPreparedStatementCache statementCache = accessor.getStatementCache(); - PreparedStatement stmt = null; - - long timeStamp = revision.getTimeStamp(); - int branchID = revision.getBranch().getID(); - - try - { - if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE) - { - stmt = statementCache.getPreparedStatement(sqlSelectAttributesByTime, ReuseProbability.MEDIUM); - idHandler.setCDOID(stmt, 1, revision.getID()); - stmt.setInt(2, branchID); - stmt.setLong(3, timeStamp); - stmt.setLong(4, timeStamp); - } - else - { - stmt = statementCache.getPreparedStatement(sqlSelectCurrentAttributes, ReuseProbability.HIGH); - idHandler.setCDOID(stmt, 1, revision.getID()); - stmt.setInt(2, branchID); - } - - // Read singleval-attribute table always (even without modeled attributes!) - boolean success = readValuesFromStatement(stmt, revision, accessor); - - // Read multival tables only if revision exists - if (success && revision.getVersion() >= CDOBranchVersion.FIRST_VERSION) - { - readLists(accessor, revision, listChunk); - } - - return success; - } - catch (SQLException ex) - { - throw new DBException(ex); - } - finally - { - statementCache.releasePreparedStatement(stmt); - } - } - - public boolean readRevisionByVersion(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk) - { - IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); - IPreparedStatementCache statementCache = accessor.getStatementCache(); - PreparedStatement stmt = null; - - try - { - stmt = statementCache.getPreparedStatement(sqlSelectAttributesByVersion, ReuseProbability.HIGH); - idHandler.setCDOID(stmt, 1, revision.getID()); - stmt.setInt(2, revision.getBranch().getID()); - stmt.setInt(3, revision.getVersion()); - - // Read singleval-attribute table always (even without modeled attributes!) - boolean success = readValuesFromStatement(stmt, revision, accessor); - - // Read multival tables only if revision exists - if (success) - { - readLists(accessor, revision, listChunk); - } - - return success; - } - catch (SQLException ex) - { - throw new DBException(ex); - } - finally - { - statementCache.releasePreparedStatement(stmt); - } - } - - public PreparedStatement createResourceQueryStatement(IDBStoreAccessor accessor, CDOID folderId, String name, - boolean exactMatch, CDOBranchPoint branchPoint) - { - EStructuralFeature nameFeature = EresourcePackage.eINSTANCE.getCDOResourceNode_Name(); - - ITypeMapping nameValueMapping = getValueMapping(nameFeature); - if (nameValueMapping == null) - { - throw new ImplementationError(nameFeature + " not found in ClassMapping " + this); //$NON-NLS-1$ - } - - int branchID = branchPoint.getBranch().getID(); - long timeStamp = branchPoint.getTimeStamp(); - - StringBuilder builder = new StringBuilder(); - builder.append("SELECT "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_ID); - builder.append(" FROM "); //$NON-NLS-1$ - builder.append(getTable()); - builder.append(" WHERE "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_VERSION); - builder.append(">0 AND "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_BRANCH); - builder.append("=? AND "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_CONTAINER); - builder.append("=? AND "); //$NON-NLS-1$ - builder.append(nameValueMapping.getField()); - if (name == null) - { - builder.append(" IS NULL"); //$NON-NLS-1$ - } - else - { - builder.append(exactMatch ? " =?" : " LIKE ?"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - builder.append(" AND ("); //$NON-NLS-1$ - - if (timeStamp == CDORevision.UNSPECIFIED_DATE) - { - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("=0)"); //$NON-NLS-1$ - } - else - { - builder.append(CDODBSchema.ATTRIBUTES_CREATED); - builder.append("<=? AND ("); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("=0 OR "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append(">=?))"); //$NON-NLS-1$ - } - - IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); - IPreparedStatementCache statementCache = accessor.getStatementCache(); - PreparedStatement stmt = null; - - try - { - int column = 1; - - stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.MEDIUM); - stmt.setInt(column++, branchID); - idHandler.setCDOID(stmt, column++, folderId); - - if (name != null) - { - String queryName = exactMatch ? name : name + "%"; //$NON-NLS-1$ - nameValueMapping.setValue(stmt, column++, queryName); - } - - if (timeStamp != CDORevision.UNSPECIFIED_DATE) - { - stmt.setLong(column++, timeStamp); - stmt.setLong(column++, timeStamp); - } - - if (TRACER.isEnabled()) - { - TRACER.format("Created Resource Query: {0}", stmt.toString()); //$NON-NLS-1$ - } - - return stmt; - } - catch (SQLException ex) - { - statementCache.releasePreparedStatement(stmt); // only release on error - throw new DBException(ex); - } - } - - public PreparedStatement createObjectIDStatement(IDBStoreAccessor accessor) - { - if (TRACER.isEnabled()) - { - TRACER.format("Created ObjectID Statement : {0}", sqlSelectAllObjectIDs); //$NON-NLS-1$ - } - - IPreparedStatementCache statementCache = accessor.getStatementCache(); - return statementCache.getPreparedStatement(sqlSelectAllObjectIDs, ReuseProbability.HIGH); - } - - @Override - protected final void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision) - { - IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); - IPreparedStatementCache statementCache = accessor.getStatementCache(); - PreparedStatement stmt = null; - - try - { - int column = 1; - stmt = statementCache.getPreparedStatement(sqlInsertAttributes, ReuseProbability.HIGH); - idHandler.setCDOID(stmt, column++, revision.getID()); - stmt.setInt(column++, revision.getVersion()); - stmt.setInt(column++, revision.getBranch().getID()); - stmt.setLong(column++, revision.getTimeStamp()); - stmt.setLong(column++, revision.getRevised()); - idHandler.setCDOID(stmt, column++, revision.getResourceID()); - idHandler.setCDOID(stmt, column++, (CDOID)revision.getContainerID()); - stmt.setInt(column++, revision.getContainingFeatureID()); - - int isSetCol = column + getValueMappings().size(); - - for (ITypeMapping mapping : getValueMappings()) - { - EStructuralFeature feature = mapping.getFeature(); - if (feature.isUnsettable()) - { - if (revision.getValue(feature) == null) - { - stmt.setBoolean(isSetCol++, false); - - // also set value column to default value - mapping.setDefaultValue(stmt, column++); - continue; - } - - stmt.setBoolean(isSetCol++, true); - } - - mapping.setValueFromRevision(stmt, column++, revision); - } - - Map<EStructuralFeature, String> listSizeFields = getListSizeFields(); - if (listSizeFields != null) - { - // isSetCol now points to the first listTableSize-column - column = isSetCol; - - for (EStructuralFeature feature : listSizeFields.keySet()) - { - CDOList list = revision.getList(feature); - stmt.setInt(column++, list.size()); - } - } - - DBUtil.update(stmt, true); - } - catch (SQLException e) - { - throw new DBException(e); - } - finally - { - statementCache.releasePreparedStatement(stmt); - } - } - - @Override - protected void detachAttributes(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, long timeStamp, - OMMonitor mon) - { - IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); - IPreparedStatementCache statementCache = accessor.getStatementCache(); - PreparedStatement stmt = null; - - try - { - stmt = statementCache.getPreparedStatement(sqlInsertAttributes, ReuseProbability.HIGH); - - int column = 1; - idHandler.setCDOID(stmt, column++, id); - stmt.setInt(column++, -version); // cdo_version - stmt.setInt(column++, branch.getID()); - stmt.setLong(column++, timeStamp); // cdo_created - stmt.setLong(column++, CDOBranchPoint.UNSPECIFIED_DATE); // cdo_revised - idHandler.setCDOID(stmt, column++, CDOID.NULL); // resource - idHandler.setCDOID(stmt, column++, CDOID.NULL); // container - stmt.setInt(column++, 0); // containing feature ID - - int isSetCol = column + getValueMappings().size(); - - for (ITypeMapping mapping : getValueMappings()) - { - EStructuralFeature feature = mapping.getFeature(); - if (feature.isUnsettable()) - { - stmt.setBoolean(isSetCol++, false); - } - - mapping.setDefaultValue(stmt, column++); - } - - Map<EStructuralFeature, String> listSizeFields = getListSizeFields(); - if (listSizeFields != null) - { - // list size columns begin after isSet-columns - column = isSetCol; - - for (int i = 0; i < listSizeFields.size(); i++) - { - stmt.setInt(column++, 0); - } - } - - DBUtil.update(stmt, true); - } - catch (SQLException e) - { - throw new DBException(e); - } - finally - { - statementCache.releasePreparedStatement(stmt); - } - } - - @Override - protected void reviseOldRevision(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, long revised) - { - IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); - IPreparedStatementCache statementCache = accessor.getStatementCache(); - PreparedStatement stmt = null; - - try - { - stmt = statementCache.getPreparedStatement(sqlReviseAttributes, ReuseProbability.HIGH); - - stmt.setLong(1, revised); - idHandler.setCDOID(stmt, 2, id); - stmt.setInt(3, branch.getID()); - - DBUtil.update(stmt, false); // No row affected if old revision from other branch! - } - catch (SQLException e) - { - throw new DBException(e); - } - finally - { - statementCache.releasePreparedStatement(stmt); - } - } - - @Override - public void writeRevision(IDBStoreAccessor accessor, InternalCDORevision revision, boolean mapType, boolean revise, - OMMonitor monitor) - { - Async async = null; - monitor.begin(10); - - try - { - try - { - async = monitor.forkAsync(); - CDOID id = revision.getID(); - if (mapType) - { - // put new objects into objectTypeMapper - long timeStamp = revision.getTimeStamp(); - AbstractHorizontalMappingStrategy mappingStrategy = (AbstractHorizontalMappingStrategy)getMappingStrategy(); - mappingStrategy.putObjectType(accessor, timeStamp, id, getEClass()); - } - else if (revise && revision.getVersion() > CDOBranchVersion.FIRST_VERSION) - { - // if revision is not the first one, revise the old revision - long revised = revision.getTimeStamp() - 1; - reviseOldRevision(accessor, id, revision.getBranch(), revised); - for (IListMapping mapping : getListMappings()) - { - mapping.objectDetached(accessor, id, revised); - } - } - } - finally - { - if (async != null) - { - async.stop(); - } - } - - try - { - async = monitor.forkAsync(); - if (revision.isResourceFolder() || revision.isResource()) - { - checkDuplicateResources(accessor, revision); - } - } - finally - { - if (async != null) - { - async.stop(); - } - } - - try - { - // Write attribute table always (even without modeled attributes!) - async = monitor.forkAsync(); - writeValues(accessor, revision); - } - finally - { - if (async != null) - { - async.stop(); - } - } - - try - { - // Write list tables only if they exist - async = monitor.forkAsync(7); - if (getListMappings() != null) - { - writeLists(accessor, revision); - } - } - finally - { - if (async != null) - { - async.stop(); - } - } - } - finally - { - monitor.done(); - } - } - - @Override - public void handleRevisions(IDBStoreAccessor accessor, CDOBranch branch, long timeStamp, boolean exactTime, - CDORevisionHandler handler) - { - StringBuilder builder = new StringBuilder(sqlSelectForHandle); - boolean whereAppend = false; - - if (branch != null) - { - // TODO: Prepare this string literal - builder.append(" WHERE "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_BRANCH); - builder.append("=?"); //$NON-NLS-1$ - - whereAppend = true; - } - - int timeParameters = 0; - if (timeStamp != CDOBranchPoint.INVALID_DATE) - { - if (exactTime) - { - if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE) - { - builder.append(whereAppend ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$ - builder.append(CDODBSchema.ATTRIBUTES_CREATED); - builder.append("=?"); //$NON-NLS-1$ - timeParameters = 1; - } - } - else - { - builder.append(whereAppend ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$ - if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE) - { - builder.append(CDODBSchema.ATTRIBUTES_CREATED); - builder.append("<=? AND ("); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("=0 OR "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append(">=?)"); //$NON-NLS-1$ - timeParameters = 2; - } - else - { - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("="); //$NON-NLS-1$ - builder.append(CDOBranchPoint.UNSPECIFIED_DATE); - } - } - } - - IRepository repository = accessor.getStore().getRepository(); - CDORevisionManager revisionManager = repository.getRevisionManager(); - CDOBranchManager branchManager = repository.getBranchManager(); - - IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); - IPreparedStatementCache statementCache = accessor.getStatementCache(); - PreparedStatement stmt = null; - ResultSet resultSet = null; - - try - { - stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.LOW); - - int column = 1; - if (branch != null) - { - stmt.setInt(column++, branch.getID()); - } - - for (int i = 0; i < timeParameters; i++) - { - stmt.setLong(column++, timeStamp); - } - - resultSet = stmt.executeQuery(); - while (resultSet.next()) - { - CDOID id = idHandler.getCDOID(resultSet, 1); - int version = resultSet.getInt(2); - - if (version >= CDOBranchVersion.FIRST_VERSION) - { - int branchID = resultSet.getInt(3); - CDOBranchVersion branchVersion = branchManager.getBranch(branchID).getVersion(Math.abs(version)); - InternalCDORevision revision = (InternalCDORevision)revisionManager.getRevisionByVersion(id, branchVersion, - CDORevision.UNCHUNKED, true); - - if (!handler.handleRevision(revision)) - { - break; - } - } - else - { - // Tell handler about detached IDs - InternalCDORevision revision = new DetachedCDORevision(null, id, null, version, 0); - handler.handleRevision(revision); - } - } - } - catch (SQLException e) - { - throw new DBException(e); - } - finally - { - DBUtil.close(resultSet); - statementCache.releasePreparedStatement(stmt); - } - } - - @Override - public Set<CDOID> readChangeSet(IDBStoreAccessor accessor, CDOChangeSetSegment[] segments) - { - StringBuilder builder = new StringBuilder(sqlSelectForChangeSet); - boolean isFirst = true; - - for (int i = 0; i < segments.length; i++) - { - if (isFirst) - { - isFirst = false; - } - else - { - builder.append(" OR "); //$NON-NLS-1$ - } - - builder.append(CDODBSchema.ATTRIBUTES_BRANCH); - builder.append("=? AND "); //$NON-NLS-1$ - - builder.append(CDODBSchema.ATTRIBUTES_CREATED); - builder.append(">=?"); //$NON-NLS-1$ - builder.append(" AND ("); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("<=? OR "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("="); //$NON-NLS-1$ - builder.append(CDOBranchPoint.UNSPECIFIED_DATE); - builder.append(")"); //$NON-NLS-1$ - } - - IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler(); - IPreparedStatementCache statementCache = accessor.getStatementCache(); - PreparedStatement stmt = null; - ResultSet resultSet = null; - - Set<CDOID> result = new HashSet<CDOID>(); - - try - { - stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.LOW); - int column = 1; - for (CDOChangeSetSegment segment : segments) - { - stmt.setInt(column++, segment.getBranch().getID()); - stmt.setLong(column++, segment.getTimeStamp()); - stmt.setLong(column++, segment.getEndTime()); - } - - resultSet = stmt.executeQuery(); - while (resultSet.next()) - { - CDOID id = idHandler.getCDOID(resultSet, 1); - result.add(id); - } - - return result; - } - catch (SQLException e) - { - throw new DBException(e); - } - finally - { - DBUtil.close(resultSet); - statementCache.releasePreparedStatement(stmt); - } - } - - @Override - protected String getListXRefsWhere(QueryXRefsContext context) - { - StringBuilder builder = new StringBuilder(); - builder.append(CDODBSchema.ATTRIBUTES_BRANCH); - builder.append("="); - builder.append(context.getBranch().getID()); - builder.append(" AND ("); - - long timeStamp = context.getTimeStamp(); - if (timeStamp == CDORevision.UNSPECIFIED_DATE) - { - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("=0)"); //$NON-NLS-1$ - } - else - { - builder.append(CDODBSchema.ATTRIBUTES_CREATED); - builder.append("<="); - builder.append(timeStamp); - builder.append(" AND ("); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append("=0 OR "); //$NON-NLS-1$ - builder.append(CDODBSchema.ATTRIBUTES_REVISED); - builder.append(">="); - builder.append(timeStamp); - builder.append("))"); //$NON-NLS-1$ - } - - return builder.toString(); - } - - public void writeRevisionDelta(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created, - OMMonitor monitor) - { - monitor.begin(); - - try - { - if (accessor.getTransaction().getBranch() != delta.getBranch()) - { - // new branch -> decide, if branch should be copied - if (((HorizontalBranchingMappingStrategyWithRanges)getMappingStrategy()).shallCopyOnBranch()) - { - doCopyOnBranch(accessor, delta, created, monitor.fork()); - return; - } - } - - Async async = null; - - try - { - async = monitor.forkAsync(); - FeatureDeltaWriter writer = deltaWriter.get(); - writer.process(accessor, delta, created); - } - finally - { - if (async != null) - { - async.stop(); - } - } - } - finally - { - monitor.done(); - } - } - - private void doCopyOnBranch(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created, OMMonitor monitor) - { - monitor.begin(2); - try - { - InternalRepository repository = (InternalRepository)accessor.getStore().getRepository(); - - InternalCDORevision oldRevision = (InternalCDORevision)accessor.getTransaction().getRevision(delta.getID()); - if (oldRevision == null) - { - throw new IllegalStateException("Origin revision not found for " + delta); - } - - // Make sure all chunks are loaded - repository.ensureChunks(oldRevision); - - InternalCDORevision newRevision = oldRevision.copy(); - newRevision.adjustForCommit(accessor.getTransaction().getBranch(), created); - delta.apply(newRevision); - monitor.worked(); - writeRevision(accessor, newRevision, false, true, monitor.fork()); - } - finally - { - monitor.done(); - } - } -} +/*
+ * 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
+ * Stefan Winkler - major refactoring
+ * Stefan Winkler - 249610: [DB] Support external references (Implementation)
+ * Stefan Winkler - derived branch mapping from audit mapping
+ * Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+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.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.eresource.EresourcePackage;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMappingAuditSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+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.server.InternalRepository;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 3.0
+ */
+public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapping implements
+ IClassMappingAuditSupport, IClassMappingDeltaSupport
+{
+ /**
+ * @author Stefan Winkler
+ */
+ private class FeatureDeltaWriter implements CDOFeatureDeltaVisitor
+ {
+ private IDBStoreAccessor accessor;
+
+ private long created;
+
+ private CDOID id;
+
+ private CDOBranch targetBranch;
+
+ private int oldVersion;
+
+ private int newVersion;
+
+ private InternalCDORevision newRevision;
+
+ public void process(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created)
+ {
+ this.accessor = accessor;
+ this.created = created;
+ id = delta.getID();
+ oldVersion = delta.getVersion();
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("FeatureDeltaWriter: old version: {0}, new version: {1}", oldVersion, oldVersion + 1); //$NON-NLS-1$
+ }
+
+ InternalCDORevision originalRevision = (InternalCDORevision)accessor.getTransaction().getRevision(id);
+ newRevision = originalRevision.copy();
+ targetBranch = accessor.getTransaction().getBranch();
+ newRevision.adjustForCommit(targetBranch, created);
+
+ newVersion = newRevision.getVersion();
+
+ // process revision delta tree
+ delta.accept(this);
+
+ if (newVersion != CDORevision.FIRST_VERSION)
+ {
+ reviseOldRevision(accessor, id, delta.getBranch(), newRevision.getTimeStamp() - 1);
+ }
+
+ writeValues(accessor, newRevision);
+ }
+
+ public void visit(CDOMoveFeatureDelta delta)
+ {
+ throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+ }
+
+ public void visit(CDOAddFeatureDelta delta)
+ {
+ throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+ }
+
+ public void visit(CDORemoveFeatureDelta delta)
+ {
+ throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+ }
+
+ public void visit(CDOSetFeatureDelta delta)
+ {
+ delta.apply(newRevision);
+ }
+
+ public void visit(CDOUnsetFeatureDelta delta)
+ {
+ delta.apply(newRevision);
+ }
+
+ public void visit(CDOListFeatureDelta delta)
+ {
+ delta.apply(newRevision);
+ IListMappingDeltaSupport listMapping = (IListMappingDeltaSupport)getListMapping(delta.getFeature());
+ listMapping.processDelta(accessor, id, targetBranch.getID(), oldVersion, newVersion, created, delta);
+ }
+
+ public void visit(CDOClearFeatureDelta delta)
+ {
+ throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+ }
+
+ public void visit(CDOContainerFeatureDelta delta)
+ {
+ delta.apply(newRevision);
+ }
+ }
+
+ private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, HorizontalBranchingClassMapping.class);
+
+ private String sqlInsertAttributes;
+
+ private String sqlSelectCurrentAttributes;
+
+ private String sqlSelectAllObjectIDs;
+
+ private String sqlSelectAttributesByTime;
+
+ private String sqlSelectAttributesByVersion;
+
+ private String sqlReviseAttributes;
+
+ private String sqlSelectForHandle;
+
+ private String sqlSelectForChangeSet;
+
+ private ThreadLocal<FeatureDeltaWriter> deltaWriter = new ThreadLocal<FeatureDeltaWriter>()
+ {
+ @Override
+ protected FeatureDeltaWriter initialValue()
+ {
+ return new FeatureDeltaWriter();
+ }
+ };
+
+ public HorizontalBranchingClassMapping(AbstractHorizontalMappingStrategy mappingStrategy, EClass eClass)
+ {
+ super(mappingStrategy, eClass);
+
+ initSQLStrings();
+ }
+
+ @Override
+ protected IDBField addBranchingField(IDBTable table)
+ {
+ return table.addField(CDODBSchema.ATTRIBUTES_BRANCH, DBType.INTEGER, true);
+ }
+
+ private void initSQLStrings()
+ {
+ Map<EStructuralFeature, String> unsettableFields = getUnsettableFields();
+ Map<EStructuralFeature, String> listSizeFields = getListSizeFields();
+
+ // ----------- Select Revision ---------------------------
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("SELECT "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_RESOURCE);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_FEATURE);
+
+ for (ITypeMapping singleMapping : getValueMappings())
+ {
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(singleMapping.getField());
+ }
+
+ if (unsettableFields != null)
+ {
+ for (String fieldName : unsettableFields.values())
+ {
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(fieldName);
+ }
+ }
+
+ if (listSizeFields != null)
+ {
+ for (String fieldName : listSizeFields.values())
+ {
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(fieldName);
+ }
+ }
+
+ builder.append(" FROM "); //$NON-NLS-1$
+ builder.append(getTable());
+ builder.append(" WHERE "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_ID);
+ builder.append("=? AND "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+ builder.append("=? AND ("); //$NON-NLS-1$
+ String sqlSelectAttributesPrefix = builder.toString();
+
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("=0)"); //$NON-NLS-1$
+
+ sqlSelectCurrentAttributes = builder.toString();
+
+ builder = new StringBuilder(sqlSelectAttributesPrefix);
+
+ builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+ builder.append("<=? AND ("); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("=0 OR "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append(">=?))"); //$NON-NLS-1$
+
+ sqlSelectAttributesByTime = builder.toString();
+
+ builder = new StringBuilder(sqlSelectAttributesPrefix);
+
+ builder.append("ABS("); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+ builder.append(")=?)"); //$NON-NLS-1$
+
+ sqlSelectAttributesByVersion = builder.toString();
+
+ // ----------- Insert Attributes -------------------------
+ builder = new StringBuilder();
+ builder.append("INSERT INTO "); //$NON-NLS-1$
+ builder.append(getTable());
+
+ builder.append("("); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_ID);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_RESOURCE);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_FEATURE);
+
+ for (ITypeMapping singleMapping : getValueMappings())
+ {
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(singleMapping.getField());
+ }
+
+ if (unsettableFields != null)
+ {
+ for (String fieldName : unsettableFields.values())
+ {
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(fieldName);
+ }
+ }
+
+ if (listSizeFields != null)
+ {
+ for (String fieldName : listSizeFields.values())
+ {
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(fieldName);
+ }
+ }
+
+ builder.append(") VALUES (?, ?, ?, ?, ?, ?, ?, ?"); //$NON-NLS-1$
+
+ for (int i = 0; i < getValueMappings().size(); i++)
+ {
+ builder.append(", ?"); //$NON-NLS-1$
+ }
+
+ if (unsettableFields != null)
+ {
+ for (int i = 0; i < unsettableFields.size(); i++)
+ {
+ builder.append(", ?"); //$NON-NLS-1$
+ }
+ }
+
+ if (listSizeFields != null)
+ {
+ for (int i = 0; i < listSizeFields.size(); i++)
+ {
+ builder.append(", ?"); //$NON-NLS-1$
+ }
+ }
+
+ builder.append(")"); //$NON-NLS-1$
+ sqlInsertAttributes = builder.toString();
+
+ // ----------- Update to set revised ----------------
+ builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+ builder.append(getTable());
+ builder.append(" SET "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("=? WHERE "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_ID);
+ builder.append("=? AND "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+ builder.append("=? AND "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("=0"); //$NON-NLS-1$
+ sqlReviseAttributes = builder.toString();
+
+ // ----------- Select all unrevised Object IDs ------
+ builder = new StringBuilder("SELECT "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_ID);
+ builder.append(" FROM "); //$NON-NLS-1$
+ builder.append(getTable());
+ builder.append(" WHERE "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("=0"); //$NON-NLS-1$
+ sqlSelectAllObjectIDs = builder.toString();
+
+ // ----------- Select all revisions (for handleRevision) ---
+ builder = new StringBuilder("SELECT "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_ID);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+ builder.append(" FROM "); //$NON-NLS-1$
+ builder.append(getTable());
+ sqlSelectForHandle = builder.toString();
+
+ // ----------- Select all revisions (for handleRevision) ---
+ builder = new StringBuilder("SELECT DISTINCT "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_ID);
+ builder.append(" FROM "); //$NON-NLS-1$
+ builder.append(getTable());
+ builder.append(" WHERE "); //$NON-NLS-1$
+ sqlSelectForChangeSet = builder.toString();
+ }
+
+ public boolean readRevision(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+ {
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IPreparedStatementCache statementCache = accessor.getStatementCache();
+ PreparedStatement stmt = null;
+
+ long timeStamp = revision.getTimeStamp();
+ int branchID = revision.getBranch().getID();
+
+ try
+ {
+ if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+ {
+ stmt = statementCache.getPreparedStatement(sqlSelectAttributesByTime, ReuseProbability.MEDIUM);
+ idHandler.setCDOID(stmt, 1, revision.getID());
+ stmt.setInt(2, branchID);
+ stmt.setLong(3, timeStamp);
+ stmt.setLong(4, timeStamp);
+ }
+ else
+ {
+ stmt = statementCache.getPreparedStatement(sqlSelectCurrentAttributes, ReuseProbability.HIGH);
+ idHandler.setCDOID(stmt, 1, revision.getID());
+ stmt.setInt(2, branchID);
+ }
+
+ // Read singleval-attribute table always (even without modeled attributes!)
+ boolean success = readValuesFromStatement(stmt, revision, accessor);
+
+ // Read multival tables only if revision exists
+ if (success && revision.getVersion() >= CDOBranchVersion.FIRST_VERSION)
+ {
+ readLists(accessor, revision, listChunk);
+ }
+
+ return success;
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
+ }
+ finally
+ {
+ statementCache.releasePreparedStatement(stmt);
+ }
+ }
+
+ public boolean readRevisionByVersion(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+ {
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IPreparedStatementCache statementCache = accessor.getStatementCache();
+ PreparedStatement stmt = null;
+
+ try
+ {
+ stmt = statementCache.getPreparedStatement(sqlSelectAttributesByVersion, ReuseProbability.HIGH);
+ idHandler.setCDOID(stmt, 1, revision.getID());
+ stmt.setInt(2, revision.getBranch().getID());
+ stmt.setInt(3, revision.getVersion());
+
+ // Read singleval-attribute table always (even without modeled attributes!)
+ boolean success = readValuesFromStatement(stmt, revision, accessor);
+
+ // Read multival tables only if revision exists
+ if (success)
+ {
+ readLists(accessor, revision, listChunk);
+ }
+
+ return success;
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
+ }
+ finally
+ {
+ statementCache.releasePreparedStatement(stmt);
+ }
+ }
+
+ public PreparedStatement createResourceQueryStatement(IDBStoreAccessor accessor, CDOID folderId, String name,
+ boolean exactMatch, CDOBranchPoint branchPoint)
+ {
+ EStructuralFeature nameFeature = EresourcePackage.eINSTANCE.getCDOResourceNode_Name();
+
+ ITypeMapping nameValueMapping = getValueMapping(nameFeature);
+ if (nameValueMapping == null)
+ {
+ throw new ImplementationError(nameFeature + " not found in ClassMapping " + this); //$NON-NLS-1$
+ }
+
+ int branchID = branchPoint.getBranch().getID();
+ long timeStamp = branchPoint.getTimeStamp();
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("SELECT "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_ID);
+ builder.append(" FROM "); //$NON-NLS-1$
+ builder.append(getTable());
+ builder.append(" WHERE "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+ builder.append(">0 AND "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+ builder.append("=? AND "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+ builder.append("=? AND "); //$NON-NLS-1$
+ builder.append(nameValueMapping.getField());
+ if (name == null)
+ {
+ builder.append(" IS NULL"); //$NON-NLS-1$
+ }
+ else
+ {
+ builder.append(exactMatch ? " =?" : " LIKE ?"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ builder.append(" AND ("); //$NON-NLS-1$
+
+ if (timeStamp == CDORevision.UNSPECIFIED_DATE)
+ {
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("=0)"); //$NON-NLS-1$
+ }
+ else
+ {
+ builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+ builder.append("<=? AND ("); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("=0 OR "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append(">=?))"); //$NON-NLS-1$
+ }
+
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IPreparedStatementCache statementCache = accessor.getStatementCache();
+ PreparedStatement stmt = null;
+
+ try
+ {
+ int column = 1;
+
+ stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.MEDIUM);
+ stmt.setInt(column++, branchID);
+ idHandler.setCDOID(stmt, column++, folderId);
+
+ if (name != null)
+ {
+ String queryName = exactMatch ? name : name + "%"; //$NON-NLS-1$
+ nameValueMapping.setValue(stmt, column++, queryName);
+ }
+
+ if (timeStamp != CDORevision.UNSPECIFIED_DATE)
+ {
+ stmt.setLong(column++, timeStamp);
+ stmt.setLong(column++, timeStamp);
+ }
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Created Resource Query: {0}", stmt.toString()); //$NON-NLS-1$
+ }
+
+ return stmt;
+ }
+ catch (SQLException ex)
+ {
+ statementCache.releasePreparedStatement(stmt); // only release on error
+ throw new DBException(ex);
+ }
+ }
+
+ public PreparedStatement createObjectIDStatement(IDBStoreAccessor accessor)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Created ObjectID Statement : {0}", sqlSelectAllObjectIDs); //$NON-NLS-1$
+ }
+
+ IPreparedStatementCache statementCache = accessor.getStatementCache();
+ return statementCache.getPreparedStatement(sqlSelectAllObjectIDs, ReuseProbability.HIGH);
+ }
+
+ @Override
+ protected final void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision)
+ {
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IPreparedStatementCache statementCache = accessor.getStatementCache();
+ PreparedStatement stmt = null;
+
+ try
+ {
+ int column = 1;
+ stmt = statementCache.getPreparedStatement(sqlInsertAttributes, ReuseProbability.HIGH);
+ idHandler.setCDOID(stmt, column++, revision.getID());
+ stmt.setInt(column++, revision.getVersion());
+ stmt.setInt(column++, revision.getBranch().getID());
+ stmt.setLong(column++, revision.getTimeStamp());
+ stmt.setLong(column++, revision.getRevised());
+ idHandler.setCDOID(stmt, column++, revision.getResourceID());
+ idHandler.setCDOID(stmt, column++, (CDOID)revision.getContainerID());
+ stmt.setInt(column++, revision.getContainingFeatureID());
+
+ int isSetCol = column + getValueMappings().size();
+
+ for (ITypeMapping mapping : getValueMappings())
+ {
+ EStructuralFeature feature = mapping.getFeature();
+ if (feature.isUnsettable())
+ {
+ if (revision.getValue(feature) == null)
+ {
+ stmt.setBoolean(isSetCol++, false);
+
+ // also set value column to default value
+ mapping.setDefaultValue(stmt, column++);
+ continue;
+ }
+
+ stmt.setBoolean(isSetCol++, true);
+ }
+
+ mapping.setValueFromRevision(stmt, column++, revision);
+ }
+
+ Map<EStructuralFeature, String> listSizeFields = getListSizeFields();
+ if (listSizeFields != null)
+ {
+ // isSetCol now points to the first listTableSize-column
+ column = isSetCol;
+
+ for (EStructuralFeature feature : listSizeFields.keySet())
+ {
+ CDOList list = revision.getList(feature);
+ stmt.setInt(column++, list.size());
+ }
+ }
+
+ DBUtil.update(stmt, true);
+ }
+ catch (SQLException e)
+ {
+ throw new DBException(e);
+ }
+ finally
+ {
+ statementCache.releasePreparedStatement(stmt);
+ }
+ }
+
+ @Override
+ protected void detachAttributes(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, long timeStamp,
+ OMMonitor mon)
+ {
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IPreparedStatementCache statementCache = accessor.getStatementCache();
+ PreparedStatement stmt = null;
+
+ try
+ {
+ stmt = statementCache.getPreparedStatement(sqlInsertAttributes, ReuseProbability.HIGH);
+
+ int column = 1;
+ idHandler.setCDOID(stmt, column++, id);
+ stmt.setInt(column++, -version); // cdo_version
+ stmt.setInt(column++, branch.getID());
+ stmt.setLong(column++, timeStamp); // cdo_created
+ stmt.setLong(column++, CDOBranchPoint.UNSPECIFIED_DATE); // cdo_revised
+ idHandler.setCDOID(stmt, column++, CDOID.NULL); // resource
+ idHandler.setCDOID(stmt, column++, CDOID.NULL); // container
+ stmt.setInt(column++, 0); // containing feature ID
+
+ int isSetCol = column + getValueMappings().size();
+
+ for (ITypeMapping mapping : getValueMappings())
+ {
+ EStructuralFeature feature = mapping.getFeature();
+ if (feature.isUnsettable())
+ {
+ stmt.setBoolean(isSetCol++, false);
+ }
+
+ mapping.setDefaultValue(stmt, column++);
+ }
+
+ Map<EStructuralFeature, String> listSizeFields = getListSizeFields();
+ if (listSizeFields != null)
+ {
+ // list size columns begin after isSet-columns
+ column = isSetCol;
+
+ for (int i = 0; i < listSizeFields.size(); i++)
+ {
+ stmt.setInt(column++, 0);
+ }
+ }
+
+ DBUtil.update(stmt, true);
+ }
+ catch (SQLException e)
+ {
+ throw new DBException(e);
+ }
+ finally
+ {
+ statementCache.releasePreparedStatement(stmt);
+ }
+ }
+
+ @Override
+ protected void reviseOldRevision(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, long revised)
+ {
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IPreparedStatementCache statementCache = accessor.getStatementCache();
+ PreparedStatement stmt = null;
+
+ try
+ {
+ stmt = statementCache.getPreparedStatement(sqlReviseAttributes, ReuseProbability.HIGH);
+
+ stmt.setLong(1, revised);
+ idHandler.setCDOID(stmt, 2, id);
+ stmt.setInt(3, branch.getID());
+
+ DBUtil.update(stmt, false); // No row affected if old revision from other branch!
+ }
+ catch (SQLException e)
+ {
+ throw new DBException(e);
+ }
+ finally
+ {
+ statementCache.releasePreparedStatement(stmt);
+ }
+ }
+
+ @Override
+ public void writeRevision(IDBStoreAccessor accessor, InternalCDORevision revision, boolean mapType, boolean revise,
+ OMMonitor monitor)
+ {
+ Async async = null;
+ monitor.begin(10);
+
+ try
+ {
+ try
+ {
+ async = monitor.forkAsync();
+ CDOID id = revision.getID();
+ if (mapType)
+ {
+ // put new objects into objectTypeMapper
+ long timeStamp = revision.getTimeStamp();
+ AbstractHorizontalMappingStrategy mappingStrategy = (AbstractHorizontalMappingStrategy)getMappingStrategy();
+ mappingStrategy.putObjectType(accessor, timeStamp, id, getEClass());
+ }
+ else if (revise && revision.getVersion() > CDOBranchVersion.FIRST_VERSION)
+ {
+ // if revision is not the first one, revise the old revision
+ long revised = revision.getTimeStamp() - 1;
+ reviseOldRevision(accessor, id, revision.getBranch(), revised);
+ for (IListMapping mapping : getListMappings())
+ {
+ mapping.objectDetached(accessor, id, revised);
+ }
+ }
+ }
+ finally
+ {
+ if (async != null)
+ {
+ async.stop();
+ }
+ }
+
+ try
+ {
+ async = monitor.forkAsync();
+ if (revision.isResourceFolder() || revision.isResource())
+ {
+ checkDuplicateResources(accessor, revision);
+ }
+ }
+ finally
+ {
+ if (async != null)
+ {
+ async.stop();
+ }
+ }
+
+ try
+ {
+ // Write attribute table always (even without modeled attributes!)
+ async = monitor.forkAsync();
+ writeValues(accessor, revision);
+ }
+ finally
+ {
+ if (async != null)
+ {
+ async.stop();
+ }
+ }
+
+ try
+ {
+ // Write list tables only if they exist
+ async = monitor.forkAsync(7);
+ if (getListMappings() != null)
+ {
+ writeLists(accessor, revision);
+ }
+ }
+ finally
+ {
+ if (async != null)
+ {
+ async.stop();
+ }
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ @Override
+ public void handleRevisions(IDBStoreAccessor accessor, CDOBranch branch, long timeStamp, boolean exactTime,
+ CDORevisionHandler handler)
+ {
+ StringBuilder builder = new StringBuilder(sqlSelectForHandle);
+ boolean whereAppend = false;
+
+ if (branch != null)
+ {
+ // TODO: Prepare this string literal
+ builder.append(" WHERE "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+ builder.append("=?"); //$NON-NLS-1$
+
+ whereAppend = true;
+ }
+
+ int timeParameters = 0;
+ if (timeStamp != CDOBranchPoint.INVALID_DATE)
+ {
+ if (exactTime)
+ {
+ if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+ {
+ builder.append(whereAppend ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$
+ builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+ builder.append("=?"); //$NON-NLS-1$
+ timeParameters = 1;
+ }
+ }
+ else
+ {
+ builder.append(whereAppend ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$
+ if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+ {
+ builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+ builder.append("<=? AND ("); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("=0 OR "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append(">=?)"); //$NON-NLS-1$
+ timeParameters = 2;
+ }
+ else
+ {
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("="); //$NON-NLS-1$
+ builder.append(CDOBranchPoint.UNSPECIFIED_DATE);
+ }
+ }
+ }
+
+ IRepository repository = accessor.getStore().getRepository();
+ CDORevisionManager revisionManager = repository.getRevisionManager();
+ CDOBranchManager branchManager = repository.getBranchManager();
+
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IPreparedStatementCache statementCache = accessor.getStatementCache();
+ PreparedStatement stmt = null;
+ ResultSet resultSet = null;
+
+ try
+ {
+ stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.LOW);
+
+ int column = 1;
+ if (branch != null)
+ {
+ stmt.setInt(column++, branch.getID());
+ }
+
+ for (int i = 0; i < timeParameters; i++)
+ {
+ stmt.setLong(column++, timeStamp);
+ }
+
+ resultSet = stmt.executeQuery();
+ while (resultSet.next())
+ {
+ CDOID id = idHandler.getCDOID(resultSet, 1);
+ int version = resultSet.getInt(2);
+
+ if (version >= CDOBranchVersion.FIRST_VERSION)
+ {
+ int branchID = resultSet.getInt(3);
+ CDOBranchVersion branchVersion = branchManager.getBranch(branchID).getVersion(Math.abs(version));
+ InternalCDORevision revision = (InternalCDORevision)revisionManager.getRevisionByVersion(id, branchVersion,
+ CDORevision.UNCHUNKED, true);
+
+ if (!handler.handleRevision(revision))
+ {
+ break;
+ }
+ }
+ else
+ {
+ // Tell handler about detached IDs
+ InternalCDORevision revision = new DetachedCDORevision(null, id, null, version, 0);
+ handler.handleRevision(revision);
+ }
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new DBException(e);
+ }
+ finally
+ {
+ DBUtil.close(resultSet);
+ statementCache.releasePreparedStatement(stmt);
+ }
+ }
+
+ @Override
+ public Set<CDOID> readChangeSet(IDBStoreAccessor accessor, CDOChangeSetSegment[] segments)
+ {
+ StringBuilder builder = new StringBuilder(sqlSelectForChangeSet);
+ boolean isFirst = true;
+
+ for (int i = 0; i < segments.length; i++)
+ {
+ if (isFirst)
+ {
+ isFirst = false;
+ }
+ else
+ {
+ builder.append(" OR "); //$NON-NLS-1$
+ }
+
+ builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+ builder.append("=? AND "); //$NON-NLS-1$
+
+ builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+ builder.append(">=?"); //$NON-NLS-1$
+ builder.append(" AND ("); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("<=? OR "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("="); //$NON-NLS-1$
+ builder.append(CDOBranchPoint.UNSPECIFIED_DATE);
+ builder.append(")"); //$NON-NLS-1$
+ }
+
+ IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IPreparedStatementCache statementCache = accessor.getStatementCache();
+ PreparedStatement stmt = null;
+ ResultSet resultSet = null;
+
+ Set<CDOID> result = new HashSet<CDOID>();
+
+ try
+ {
+ stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.LOW);
+ int column = 1;
+ for (CDOChangeSetSegment segment : segments)
+ {
+ stmt.setInt(column++, segment.getBranch().getID());
+ stmt.setLong(column++, segment.getTimeStamp());
+ stmt.setLong(column++, segment.getEndTime());
+ }
+
+ resultSet = stmt.executeQuery();
+ while (resultSet.next())
+ {
+ CDOID id = idHandler.getCDOID(resultSet, 1);
+ result.add(id);
+ }
+
+ return result;
+ }
+ catch (SQLException e)
+ {
+ throw new DBException(e);
+ }
+ finally
+ {
+ DBUtil.close(resultSet);
+ statementCache.releasePreparedStatement(stmt);
+ }
+ }
+
+ @Override
+ protected String getListXRefsWhere(QueryXRefsContext context)
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+ builder.append("=");
+ builder.append(context.getBranch().getID());
+ builder.append(" AND (");
+
+ long timeStamp = context.getTimeStamp();
+ if (timeStamp == CDORevision.UNSPECIFIED_DATE)
+ {
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("=0)"); //$NON-NLS-1$
+ }
+ else
+ {
+ builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+ builder.append("<=");
+ builder.append(timeStamp);
+ builder.append(" AND ("); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append("=0 OR "); //$NON-NLS-1$
+ builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+ builder.append(">=");
+ builder.append(timeStamp);
+ builder.append("))"); //$NON-NLS-1$
+ }
+
+ return builder.toString();
+ }
+
+ public void writeRevisionDelta(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created,
+ OMMonitor monitor)
+ {
+ monitor.begin();
+
+ try
+ {
+ if (accessor.getTransaction().getBranch() != delta.getBranch())
+ {
+ // new branch -> decide, if branch should be copied
+ if (((HorizontalBranchingMappingStrategyWithRanges)getMappingStrategy()).shallCopyOnBranch())
+ {
+ doCopyOnBranch(accessor, delta, created, monitor.fork());
+ return;
+ }
+ }
+
+ Async async = null;
+
+ try
+ {
+ async = monitor.forkAsync();
+ FeatureDeltaWriter writer = deltaWriter.get();
+ writer.process(accessor, delta, created);
+ }
+ finally
+ {
+ if (async != null)
+ {
+ async.stop();
+ }
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ private void doCopyOnBranch(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created, OMMonitor monitor)
+ {
+ monitor.begin(2);
+ try
+ {
+ InternalRepository repository = (InternalRepository)accessor.getStore().getRepository();
+
+ InternalCDORevision oldRevision = (InternalCDORevision)accessor.getTransaction().getRevision(delta.getID());
+ if (oldRevision == null)
+ {
+ throw new IllegalStateException("Origin revision not found for " + 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(accessor.getTransaction().getBranch(), created);
+ delta.apply(newRevision);
+ monitor.worked();
+ writeRevision(accessor, newRevision, false, true, monitor.fork());
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingRepository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingRepository.java index 9b899553c1..d65e8a6b7f 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingRepository.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingRepository.java @@ -1,542 +1,287 @@ -/* - * 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.server; - -import org.eclipse.emf.cdo.common.branch.CDOBranch; -import org.eclipse.emf.cdo.common.branch.CDOBranchHandler; -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.CDOCommitInfoHandler; -import org.eclipse.emf.cdo.common.id.CDOID; -import org.eclipse.emf.cdo.common.id.CDOID.ObjectType; -import org.eclipse.emf.cdo.common.lob.CDOLobHandler; -import org.eclipse.emf.cdo.common.model.CDOPackageUnit; -import org.eclipse.emf.cdo.common.protocol.CDODataOutput; -import org.eclipse.emf.cdo.common.revision.CDORevision; -import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; -import org.eclipse.emf.cdo.common.revision.CDORevisionKey; -import org.eclipse.emf.cdo.common.util.CDOQueryInfo; -import org.eclipse.emf.cdo.server.IQueryHandler; -import org.eclipse.emf.cdo.server.IQueryHandlerProvider; -import org.eclipse.emf.cdo.server.IStoreAccessor; -import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext; -import org.eclipse.emf.cdo.server.ITransaction; -import org.eclipse.emf.cdo.spi.common.CDOReplicationContext; -import org.eclipse.emf.cdo.spi.common.CDOReplicationInfo; -import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager; -import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo; -import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager; -import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; -import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo; -import org.eclipse.emf.cdo.spi.server.InternalCommitContext; -import org.eclipse.emf.cdo.spi.server.InternalCommitManager; -import org.eclipse.emf.cdo.spi.server.InternalLockManager; -import org.eclipse.emf.cdo.spi.server.InternalQueryManager; -import org.eclipse.emf.cdo.spi.server.InternalRepository; -import org.eclipse.emf.cdo.spi.server.InternalSession; -import org.eclipse.emf.cdo.spi.server.InternalSessionManager; -import org.eclipse.emf.cdo.spi.server.InternalStore; -import org.eclipse.emf.cdo.spi.server.InternalTransaction; -import org.eclipse.emf.cdo.spi.server.InternalView; - -import org.eclipse.net4j.util.collection.Pair; -import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; -import org.eclipse.net4j.util.event.IListener; -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.EStructuralFeature; -import org.eclipse.emf.spi.cdo.CDOSessionProtocol.LockObjectsResult; -import org.eclipse.emf.spi.cdo.CDOSessionProtocol.UnlockObjectsResult; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Semaphore; - -/** - * @author Eike Stepper - */ -public abstract class DelegatingRepository implements InternalRepository -{ - public DelegatingRepository() - { - } - - protected abstract InternalRepository getDelegate(); - - public void addHandler(Handler handler) - { - getDelegate().addHandler(handler); - } - - public void addListener(IListener listener) - { - getDelegate().addListener(listener); - } - - public long[] createCommitTimeStamp(OMMonitor monitor) - { - return getDelegate().createCommitTimeStamp(monitor); - } - - public IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature, int chunkStart, - int chunkEnd) - { - return getDelegate().ensureChunk(revision, feature, chunkStart, chunkEnd); - } - - public InternalCommitManager getCommitManager() - { - return getDelegate().getCommitManager(); - } - - public long getCreationTime() - { - return getDelegate().getCreationTime(); - } - - public Object[] getElements() - { - return getDelegate().getElements(); - } - - public long getLastCommitTimeStamp() - { - return getDelegate().getLastCommitTimeStamp(); - } - - public IListener[] getListeners() - { - return getDelegate().getListeners(); - } - - @Deprecated - public InternalLockManager getLockManager() - { - return getDelegate().getLockingManager(); - } - - public String getName() - { - return getDelegate().getName(); - } - - public InternalCDOPackageRegistry getPackageRegistry() - { - return getDelegate().getPackageRegistry(); - } - - public InternalCDOPackageRegistry getPackageRegistry(boolean considerCommitContext) - { - return getDelegate().getPackageRegistry(considerCommitContext); - } - - public Map<String, String> getProperties() - { - return getDelegate().getProperties(); - } - - public IQueryHandler getQueryHandler(CDOQueryInfo info) - { - return getDelegate().getQueryHandler(info); - } - - public IQueryHandlerProvider getQueryHandlerProvider() - { - return getDelegate().getQueryHandlerProvider(); - } - - public InternalQueryManager getQueryManager() - { - return getDelegate().getQueryManager(); - } - - public InternalCDORevisionManager getRevisionManager() - { - return getDelegate().getRevisionManager(); - } - - public InternalSessionManager getSessionManager() - { - return getDelegate().getSessionManager(); - } - - public InternalStore getStore() - { - return getDelegate().getStore(); - } - - public String getUUID() - { - return getDelegate().getUUID(); - } - - public boolean hasListeners() - { - return getDelegate().hasListeners(); - } - - public boolean isEmpty() - { - return getDelegate().isEmpty(); - } - - public boolean isSupportingAudits() - { - return getDelegate().isSupportingAudits(); - } - - public boolean isSupportingBranches() - { - return getDelegate().isSupportingBranches(); - } - - public EPackage[] loadPackages(CDOPackageUnit packageUnit) - { - return getDelegate().loadPackages(packageUnit); - } - - public InternalCDOBranchManager getBranchManager() - { - return getDelegate().getBranchManager(); - } - - public void setBranchManager(InternalCDOBranchManager branchManager) - { - getDelegate().setBranchManager(branchManager); - } - - public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo) - { - return getDelegate().createBranch(branchID, branchInfo); - } - - public BranchInfo loadBranch(int branchID) - { - return getDelegate().loadBranch(branchID); - } - - public SubBranchInfo[] loadSubBranches(int branchID) - { - return getDelegate().loadSubBranches(branchID); - } - - public List<InternalCDORevision> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, - int referenceChunk, int prefetchDepth) - { - return getDelegate().loadRevisions(infos, branchPoint, referenceChunk, prefetchDepth); - } - - public InternalCDORevision loadRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk) - { - return getDelegate().loadRevisionByVersion(id, branchVersion, referenceChunk); - } - - public void notifyReadAccessHandlers(InternalSession session, CDORevision[] revisions, - List<CDORevision> additionalRevisions) - { - getDelegate().notifyReadAccessHandlers(session, revisions, additionalRevisions); - } - - public void notifyWriteAccessHandlers(ITransaction transaction, CommitContext commitContext, boolean beforeCommit, - OMMonitor monitor) - { - getDelegate().notifyWriteAccessHandlers(transaction, commitContext, beforeCommit, monitor); - } - - public void removeHandler(Handler handler) - { - getDelegate().removeHandler(handler); - } - - public void removeListener(IListener listener) - { - getDelegate().removeListener(listener); - } - - public void setName(String name) - { - getDelegate().setName(name); - } - - public void setProperties(Map<String, String> properties) - { - getDelegate().setProperties(properties); - } - - public void setQueryHandlerProvider(IQueryHandlerProvider queryHandlerProvider) - { - getDelegate().setQueryHandlerProvider(queryHandlerProvider); - } - - public void setRevisionManager(InternalCDORevisionManager revisionManager) - { - getDelegate().setRevisionManager(revisionManager); - } - - public void setSessionManager(InternalSessionManager sessionManager) - { - getDelegate().setSessionManager(sessionManager); - } - - public void setStore(InternalStore store) - { - getDelegate().setStore(store); - } - - public long getTimeStamp() - { - return getDelegate().getTimeStamp(); - } - - public void validateTimeStamp(long timeStamp) throws IllegalArgumentException - { - getDelegate().validateTimeStamp(timeStamp); - } - - public void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler) - { - getDelegate().loadCommitInfos(branch, startTime, endTime, handler); - } - - public CDOCommitData loadCommitData(long timeStamp) - { - return getDelegate().loadCommitData(timeStamp); - } - - public Type getType() - { - return getDelegate().getType(); - } - - public State getState() - { - return getDelegate().getState(); - } - - public String getStoreType() - { - return getDelegate().getStoreType(); - } - - public Set<ObjectType> getObjectIDTypes() - { - return getDelegate().getObjectIDTypes(); - } - - public IDGenerationLocation getIDGenerationLocation() - { - return getDelegate().getIDGenerationLocation(); - } - - public CDOID getRootResourceID() - { - return getDelegate().getRootResourceID(); - } - - public Object processPackage(Object value) - { - return getDelegate().processPackage(value); - } - - public boolean isSupportingEcore() - { - return getDelegate().isSupportingEcore(); - } - - public boolean isEnsuringReferentialIntegrity() - { - return getDelegate().isEnsuringReferentialIntegrity(); - } - - public void setType(Type type) - { - getDelegate().setType(type); - } - - public long waitForCommit(long timeout) - { - return getDelegate().waitForCommit(timeout); - } - - public void setState(State state) - { - getDelegate().setState(state); - } - - public int loadBranches(int startID, int endID, CDOBranchHandler branchHandler) - { - return getDelegate().loadBranches(startID, endID, branchHandler); - } - - public Semaphore getPackageRegistryCommitLock() - { - return getDelegate().getPackageRegistryCommitLock(); - } - - public CDOCommitInfoHandler[] getCommitInfoHandlers() - { - return getDelegate().getCommitInfoHandlers(); - } - - public void addCommitInfoHandler(CDOCommitInfoHandler handler) - { - getDelegate().addCommitInfoHandler(handler); - } - - public void removeCommitInfoHandler(CDOCommitInfoHandler handler) - { - getDelegate().removeCommitInfoHandler(handler); - } - - public InternalCDOCommitInfoManager getCommitInfoManager() - { - return getDelegate().getCommitInfoManager(); - } - - public Set<Handler> getHandlers() - { - return getDelegate().getHandlers(); - } - - public void setInitialPackages(EPackage... initialPackages) - { - getDelegate().setInitialPackages(initialPackages); - } - - public InternalLockManager getLockingManager() - { - return getDelegate().getLockingManager(); - } - - public InternalCommitContext createCommitContext(InternalTransaction transaction) - { - return getDelegate().createCommitContext(transaction); - } - - public long[] forceCommitTimeStamp(long timestamp, OMMonitor monitor) - { - return getDelegate().forceCommitTimeStamp(timestamp, monitor); - } - - public void endCommit(long timeStamp) - { - getDelegate().endCommit(timeStamp); - } - - public void failCommit(long timeStamp) - { - getDelegate().failCommit(timeStamp); - } - - public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo) - { - getDelegate().sendCommitNotification(sender, commitInfo); - } - - public void setRootResourceID(CDOID rootResourceID) - { - getDelegate().setRootResourceID(rootResourceID); - } - - public void setLastCommitTimeStamp(long commitTimeStamp) - { - getDelegate().setLastCommitTimeStamp(commitTimeStamp); - } - - public void ensureChunks(InternalCDORevision revision) - { - getDelegate().ensureChunks(revision); - } - - public void replicate(CDOReplicationContext context) - { - getDelegate().replicate(context); - } - - public CDOReplicationInfo replicateRaw(CDODataOutput out, int lastReplicatedBranchID, long lastReplicatedCommitTime) - throws IOException - { - return getDelegate().replicateRaw(out, lastReplicatedBranchID, lastReplicatedCommitTime); - } - - public CDOChangeSetData getChangeSet(CDOBranchPoint startPoint, CDOBranchPoint endPoint) - { - return getDelegate().getChangeSet(startPoint, endPoint); - } - - public Set<CDOID> getMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, - CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor) - { - return getDelegate().getMergeData(targetInfo, sourceInfo, targetBaseInfo, sourceBaseInfo, monitor); - } - - public void queryLobs(List<byte[]> ids) - { - getDelegate().queryLobs(ids); - } - - public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException - { - getDelegate().handleLobs(fromTime, toTime, handler); - } - - public void loadLob(byte[] id, OutputStream out) throws IOException - { - getDelegate().loadLob(id, out); - } - - public void handleRevisions(EClass eClass, CDOBranch branch, boolean exactBranch, long timeStamp, boolean exactTime, - CDORevisionHandler handler) - { - getDelegate().handleRevisions(eClass, branch, exactBranch, timeStamp, exactTime, handler); - } - - public boolean isSkipInitialization() - { - return getDelegate().isSkipInitialization(); - } - - public void setSkipInitialization(boolean skipInitialization) - { - getDelegate().setSkipInitialization(skipInitialization); - } - - public void initSystemPackages() - { - getDelegate().initSystemPackages(); - } - - public void initMainBranch(InternalCDOBranchManager branchManager, long timeStamp) - { - getDelegate().initMainBranch(branchManager, timeStamp); - } - - public LockObjectsResult lock(InternalView view, LockType type, List<CDORevisionKey> keys, boolean recursive, - long timeout) - { - return getDelegate().lock(view, type, keys, recursive, timeout); - } - - public UnlockObjectsResult unlock(InternalView view, LockType type, List<CDOID> ids, boolean recursive) - { - return getDelegate().unlock(view, type, ids, recursive); - } -} +/*
+ * 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.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.IQueryHandlerProvider;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo;
+import org.eclipse.emf.cdo.spi.server.InternalCommitManager;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
+import org.eclipse.emf.cdo.spi.server.InternalQueryManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalSessionManager;
+import org.eclipse.emf.cdo.spi.server.InternalStore;
+
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class DelegatingRepository implements InternalRepository
+{
+ public DelegatingRepository()
+ {
+ }
+
+ protected abstract InternalRepository getDelegate();
+
+ public void addHandler(Handler handler)
+ {
+ getDelegate().addHandler(handler);
+ }
+
+ public void addListener(IListener listener)
+ {
+ getDelegate().addListener(listener);
+ }
+
+ public long[] createCommitTimeStamp(OMMonitor monitor)
+ {
+ return getDelegate().createCommitTimeStamp(monitor);
+ }
+
+ public IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature, int chunkStart,
+ int chunkEnd)
+ {
+ return getDelegate().ensureChunk(revision, feature, chunkStart, chunkEnd);
+ }
+
+ public InternalCommitManager getCommitManager()
+ {
+ return getDelegate().getCommitManager();
+ }
+
+ public long getCreationTime()
+ {
+ return getDelegate().getCreationTime();
+ }
+
+ public Object[] getElements()
+ {
+ return getDelegate().getElements();
+ }
+
+ public long getLastCommitTimeStamp()
+ {
+ return getDelegate().getLastCommitTimeStamp();
+ }
+
+ public IListener[] getListeners()
+ {
+ return getDelegate().getListeners();
+ }
+
+ @Deprecated
+ public InternalLockManager getLockManager()
+ {
+ return getDelegate().getLockingManager();
+ }
+
+ public String getName()
+ {
+ return getDelegate().getName();
+ }
+
+ public InternalCDOPackageRegistry getPackageRegistry()
+ {
+ return getDelegate().getPackageRegistry();
+ }
+
+ public InternalCDOPackageRegistry getPackageRegistry(boolean considerCommitContext)
+ {
+ return getDelegate().getPackageRegistry(considerCommitContext);
+ }
+
+ public Map<String, String> getProperties()
+ {
+ return getDelegate().getProperties();
+ }
+
+ public IQueryHandler getQueryHandler(CDOQueryInfo info)
+ {
+ return getDelegate().getQueryHandler(info);
+ }
+
+ public IQueryHandlerProvider getQueryHandlerProvider()
+ {
+ return getDelegate().getQueryHandlerProvider();
+ }
+
+ public InternalQueryManager getQueryManager()
+ {
+ return getDelegate().getQueryManager();
+ }
+
+ public InternalCDORevisionManager getRevisionManager()
+ {
+ return getDelegate().getRevisionManager();
+ }
+
+ public InternalSessionManager getSessionManager()
+ {
+ return getDelegate().getSessionManager();
+ }
+
+ public InternalStore getStore()
+ {
+ return getDelegate().getStore();
+ }
+
+ public String getUUID()
+ {
+ return getDelegate().getUUID();
+ }
+
+ public boolean hasListeners()
+ {
+ return getDelegate().hasListeners();
+ }
+
+ public boolean isEmpty()
+ {
+ return getDelegate().isEmpty();
+ }
+
+ public boolean isSupportingAudits()
+ {
+ return getDelegate().isSupportingAudits();
+ }
+
+ public boolean isSupportingBranches()
+ {
+ return getDelegate().isSupportingBranches();
+ }
+
+ public EPackage[] loadPackages(CDOPackageUnit packageUnit)
+ {
+ return getDelegate().loadPackages(packageUnit);
+ }
+
+ public InternalCDOBranchManager getBranchManager()
+ {
+ return getDelegate().getBranchManager();
+ }
+
+ public void setBranchManager(InternalCDOBranchManager branchManager)
+ {
+ getDelegate().setBranchManager(branchManager);
+ }
+
+ public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo)
+ {
+ return getDelegate().createBranch(branchID, branchInfo);
+ }
+
+ public BranchInfo loadBranch(int branchID)
+ {
+ return getDelegate().loadBranch(branchID);
+ }
+
+ public SubBranchInfo[] loadSubBranches(int branchID)
+ {
+ return getDelegate().loadSubBranches(branchID);
+ }
+
+ public List<InternalCDORevision> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint,
+ int referenceChunk, int prefetchDepth)
+ {
+ return getDelegate().loadRevisions(infos, branchPoint, referenceChunk, prefetchDepth);
+ }
+
+ public InternalCDORevision loadRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk)
+ {
+ return getDelegate().loadRevisionByVersion(id, branchVersion, referenceChunk);
+ }
+
+ public void notifyReadAccessHandlers(InternalSession session, CDORevision[] revisions,
+ List<CDORevision> additionalRevisions)
+ {
+ getDelegate().notifyReadAccessHandlers(session, revisions, additionalRevisions);
+ }
+
+ public void notifyWriteAccessHandlers(ITransaction transaction, CommitContext commitContext, boolean beforeCommit,
+ OMMonitor monitor)
+ {
+ getDelegate().notifyWriteAccessHandlers(transaction, commitContext, beforeCommit, monitor);
+ }
+
+ public void removeHandler(Handler handler)
+ {
+ getDelegate().removeHandler(handler);
+ }
+
+ public void removeListener(IListener listener)
+ {
+ getDelegate().removeListener(listener);
+ }
+
+ public void setName(String name)
+ {
+ getDelegate().setName(name);
+ }
+
+ public void setProperties(Map<String, String> properties)
+ {
+ getDelegate().setProperties(properties);
+ }
+
+ public void setQueryHandlerProvider(IQueryHandlerProvider queryHandlerProvider)
+ {
+ getDelegate().setQueryHandlerProvider(queryHandlerProvider);
+ }
+
+ public void setRevisionManager(InternalCDORevisionManager revisionManager)
+ {
+ getDelegate().setRevisionManager(revisionManager);
+ }
+
+ public void setSessionManager(InternalSessionManager sessionManager)
+ {
+ getDelegate().setSessionManager(sessionManager);
+ }
+
+ public void setStore(InternalStore store)
+ {
+ getDelegate().setStore(store);
+ }
+
+ public long getTimeStamp()
+ {
+ return getDelegate().getTimeStamp();
+ }
+
+ public void validateTimeStamp(long timeStamp) throws IllegalArgumentException
+ {
+ getDelegate().validateTimeStamp(timeStamp);
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java index 8347f99acc..669bf76b9d 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java @@ -1,2000 +1,1966 @@ -/* - * 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 233273 - * Simon McDuff - bug 233490 - * Stefan Winkler - changed order of determining audit and revision delta support. - * Andre Dietisheim - bug 256649 - */ -package org.eclipse.emf.cdo.internal.server; - -import org.eclipse.emf.cdo.common.CDOCommonView; -import org.eclipse.emf.cdo.common.branch.CDOBranch; -import org.eclipse.emf.cdo.common.branch.CDOBranchHandler; -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.CDOCommitInfoHandler; -import org.eclipse.emf.cdo.common.id.CDOID; -import org.eclipse.emf.cdo.common.id.CDOIDGenerator; -import org.eclipse.emf.cdo.common.id.CDOIDTemp; -import org.eclipse.emf.cdo.common.id.CDOIDUtil; -import org.eclipse.emf.cdo.common.lob.CDOLobHandler; -import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; -import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation; -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.model.EMFUtil; -import org.eclipse.emf.cdo.common.protocol.CDODataOutput; -import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; -import org.eclipse.emf.cdo.common.revision.CDORevision; -import org.eclipse.emf.cdo.common.revision.CDORevisionFactory; -import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; -import org.eclipse.emf.cdo.common.revision.CDORevisionKey; -import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; -import org.eclipse.emf.cdo.common.util.CDOCommonUtil; -import org.eclipse.emf.cdo.common.util.CDOQueryInfo; -import org.eclipse.emf.cdo.common.util.RepositoryStateChangedEvent; -import org.eclipse.emf.cdo.common.util.RepositoryTypeChangedEvent; -import org.eclipse.emf.cdo.eresource.EresourcePackage; -import org.eclipse.emf.cdo.etypes.EtypesPackage; -import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl; -import org.eclipse.emf.cdo.internal.server.bundle.OM; -import org.eclipse.emf.cdo.server.IQueryHandler; -import org.eclipse.emf.cdo.server.IQueryHandlerProvider; -import org.eclipse.emf.cdo.server.IStore; -import org.eclipse.emf.cdo.server.IStore.CanHandleClientAssignedIDs; -import org.eclipse.emf.cdo.server.IStoreAccessor; -import org.eclipse.emf.cdo.server.IStoreChunkReader; -import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk; -import org.eclipse.emf.cdo.server.ITransaction; -import org.eclipse.emf.cdo.server.IView; -import org.eclipse.emf.cdo.server.StoreThreadLocal; -import org.eclipse.emf.cdo.spi.common.CDOReplicationContext; -import org.eclipse.emf.cdo.spi.common.CDOReplicationInfo; -import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; -import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager; -import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment; -import org.eclipse.emf.cdo.spi.common.commit.CDOCommitInfoUtil; -import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo; -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.DetachedCDORevision; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; -import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision; -import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo; -import org.eclipse.emf.cdo.spi.server.ContainerQueryHandlerProvider; -import org.eclipse.emf.cdo.spi.server.InternalCommitContext; -import org.eclipse.emf.cdo.spi.server.InternalCommitManager; -import org.eclipse.emf.cdo.spi.server.InternalLockManager; -import org.eclipse.emf.cdo.spi.server.InternalQueryManager; -import org.eclipse.emf.cdo.spi.server.InternalRepository; -import org.eclipse.emf.cdo.spi.server.InternalSession; -import org.eclipse.emf.cdo.spi.server.InternalSessionManager; -import org.eclipse.emf.cdo.spi.server.InternalStore; -import org.eclipse.emf.cdo.spi.server.InternalTransaction; -import org.eclipse.emf.cdo.spi.server.InternalView; - -import org.eclipse.emf.internal.cdo.object.CDOFactoryImpl; - -import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; -import org.eclipse.net4j.util.StringUtil; -import org.eclipse.net4j.util.WrappedException; -import org.eclipse.net4j.util.collection.MoveableList; -import org.eclipse.net4j.util.collection.Pair; -import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; -import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState; -import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException; -import org.eclipse.net4j.util.container.Container; -import org.eclipse.net4j.util.container.IPluginContainer; -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.net4j.util.transaction.TransactionException; - -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EPackage; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.EcorePackage; -import org.eclipse.emf.spi.cdo.CDOSessionProtocol.LockObjectsResult; -import org.eclipse.emf.spi.cdo.CDOSessionProtocol.UnlockObjectsResult; - -import java.io.IOException; -import java.io.OutputStream; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Collection; -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.UUID; -import java.util.concurrent.Semaphore; - -/** - * @author Eike Stepper - * @since 2.0 - */ -public class Repository extends Container<Object> implements InternalRepository -{ - private String name; - - private String uuid; - - private InternalStore store; - - private Type type = Type.MASTER; - - private State state = State.ONLINE; - - private Map<String, String> properties; - - private boolean supportingAudits; - - private boolean supportingBranches; - - private boolean supportingEcore; - - private boolean ensuringReferentialIntegrity; - - private IDGenerationLocation idGenerationLocation; - - /** - * Must not be thread-bound to support XA commits. - */ - private Semaphore packageRegistryCommitLock = new Semaphore(1); - - private InternalCDOPackageRegistry packageRegistry; - - private InternalCDOBranchManager branchManager; - - private InternalCDORevisionManager revisionManager; - - private InternalCDOCommitInfoManager commitInfoManager; - - private InternalSessionManager sessionManager; - - private InternalQueryManager queryManager; - - private InternalCommitManager commitManager; - - private InternalLockManager lockingManager; - - private IQueryHandlerProvider queryHandlerProvider; - - private List<ReadAccessHandler> readAccessHandlers = new ArrayList<ReadAccessHandler>(); - - private List<WriteAccessHandler> writeAccessHandlers = new ArrayList<WriteAccessHandler>(); - - private List<CDOCommitInfoHandler> commitInfoHandlers = new ArrayList<CDOCommitInfoHandler>(); - - private EPackage[] initialPackages; - - // Bugzilla 297940 - private TimeStampAuthority timeStampAuthority = new TimeStampAuthority(this); - - @ExcludeFromDump - private transient Object createBranchLock = new Object(); - - private boolean skipInitialization; - - private CDOID rootResourceID; - - public Repository() - { - } - - public String getName() - { - return name; - } - - public void setName(String name) - { - this.name = name; - } - - public String getUUID() - { - if (uuid == null) - { - uuid = getProperties().get(Props.OVERRIDE_UUID); - if (uuid == null) - { - uuid = UUID.randomUUID().toString(); - } - else if (uuid.length() == 0) - { - uuid = getName(); - } - } - - return uuid; - } - - public InternalStore getStore() - { - return store; - } - - public void setStore(InternalStore store) - { - this.store = store; - } - - public Type getType() - { - return type; - } - - public void setType(Type type) - { - checkArg(type, "type"); //$NON-NLS-1$ - if (this.type != type) - { - changingType(this.type, type); - } - } - - protected void changingType(Type oldType, Type newType) - { - type = newType; - fireEvent(new RepositoryTypeChangedEvent(this, oldType, newType)); - - if (sessionManager != null) - { - sessionManager.sendRepositoryTypeNotification(oldType, newType); - } - } - - public State getState() - { - return state; - } - - public void setState(State state) - { - checkArg(state, "state"); //$NON-NLS-1$ - if (this.state != state) - { - changingState(this.state, state); - } - } - - protected void changingState(State oldState, State newState) - { - state = newState; - fireEvent(new RepositoryStateChangedEvent(this, oldState, newState)); - - if (sessionManager != null) - { - sessionManager.sendRepositoryStateNotification(oldState, newState, getRootResourceID()); - } - } - - public synchronized Map<String, String> getProperties() - { - if (properties == null) - { - properties = new HashMap<String, String>(); - } - - return properties; - } - - public synchronized void setProperties(Map<String, String> properties) - { - this.properties = properties; - } - - public boolean isSupportingAudits() - { - return supportingAudits; - } - - public boolean isSupportingBranches() - { - return supportingBranches; - } - - public boolean isSupportingEcore() - { - return supportingEcore; - } - - public boolean isEnsuringReferentialIntegrity() - { - return ensuringReferentialIntegrity; - } - - public IDGenerationLocation getIDGenerationLocation() - { - return idGenerationLocation; - } - - public String getStoreType() - { - return store.getType(); - } - - public Set<CDOID.ObjectType> getObjectIDTypes() - { - return store.getObjectIDTypes(); - } - - public CDOID getRootResourceID() - { - return rootResourceID; - } - - public void setRootResourceID(CDOID rootResourceID) - { - this.rootResourceID = rootResourceID; - } - - public Object processPackage(Object value) - { - CDOFactoryImpl.prepareDynamicEPackage(value); - return value; - } - - public EPackage[] loadPackages(CDOPackageUnit packageUnit) - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - return accessor.loadPackageUnit((InternalCDOPackageUnit)packageUnit); - } - - public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo) - { - if (!isSupportingBranches()) - { - throw new IllegalStateException("Branching is not supported by " + this); - } - - long baseTimeStamp = branchInfo.getBaseTimeStamp(); - if (baseTimeStamp == CDOBranchPoint.UNSPECIFIED_DATE) - { - baseTimeStamp = getTimeStamp(); - branchInfo = new BranchInfo(branchInfo.getName(), branchInfo.getBaseBranchID(), baseTimeStamp); - } - - synchronized (createBranchLock) - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - return accessor.createBranch(branchID, branchInfo); - } - } - - public BranchInfo loadBranch(int branchID) - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - return accessor.loadBranch(branchID); - } - - public SubBranchInfo[] loadSubBranches(int branchID) - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - return accessor.loadSubBranches(branchID); - } - - public int loadBranches(int startID, int endID, CDOBranchHandler branchHandler) - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - return accessor.loadBranches(startID, endID, branchHandler); - } - - public void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler) - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - accessor.loadCommitInfos(branch, startTime, endTime, handler); - } - - public CDOCommitData loadCommitData(long timeStamp) - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - return accessor.loadCommitData(timeStamp); - } - - public List<InternalCDORevision> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, - int referenceChunk, int prefetchDepth) - { - for (RevisionInfo info : infos) - { - CDOID id = info.getID(); - RevisionInfo.Type type = info.getType(); - switch (type) - { - case AVAILABLE_NORMAL: // direct == false - { - RevisionInfo.Available.Normal availableInfo = (RevisionInfo.Available.Normal)info; - checkArg(availableInfo.isDirect() == false, "Load is not needed"); - break; - } - - case AVAILABLE_POINTER: // direct == false || target == null - { - RevisionInfo.Available.Pointer pointerInfo = (RevisionInfo.Available.Pointer)info; - boolean needsTarget = !pointerInfo.hasTarget(); - checkArg(pointerInfo.isDirect() == false || needsTarget, "Load is not needed"); - - if (needsTarget) - { - CDOBranchVersion targetBranchVersion = pointerInfo.getTargetBranchVersion(); - InternalCDORevision target = loadRevisionByVersion(id, targetBranchVersion, referenceChunk); - PointerCDORevision pointer = new PointerCDORevision(target.getEClass(), id, pointerInfo - .getAvailableBranchVersion().getBranch(), CDORevision.UNSPECIFIED_DATE, target); - - info.setResult(target); - info.setSynthetic(pointer); - continue; - } - - break; - } - - case AVAILABLE_DETACHED: // direct == false - { - RevisionInfo.Available.Detached detachedInfo = (RevisionInfo.Available.Detached)info; - checkArg(detachedInfo.isDirect() == false, "Load is not needed"); - break; - } - - case MISSING: - { - break; - } - - default: - throw new IllegalStateException("Invalid revision info type: " + type); - } - - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - InternalCDORevision revision = accessor.readRevision(id, branchPoint, referenceChunk, revisionManager); - if (revision == null) - { - if (isSupportingAudits()) - { - InternalCDORevision target = loadRevisionTarget(id, branchPoint, referenceChunk, accessor); - if (target != null) - { - if (referenceChunk == CDORevision.UNCHUNKED) - { - target.setUnchunked(); - } - - CDOBranch branch = branchPoint.getBranch(); - long revised = loadRevisionRevised(id, branch); - PointerCDORevision pointer = new PointerCDORevision(target.getEClass(), id, branch, revised, target); - info.setSynthetic(pointer); - } - - info.setResult(target); - } - else - { - DetachedCDORevision detachedRevision = new DetachedCDORevision(EcorePackage.Literals.ECLASS, id, - branchPoint.getBranch(), 0, CDORevision.UNSPECIFIED_DATE); - info.setSynthetic(detachedRevision); - } - } - else if (revision instanceof DetachedCDORevision) - { - DetachedCDORevision detached = (DetachedCDORevision)revision; - info.setSynthetic(detached); - } - else - { - if (referenceChunk == CDORevision.UNCHUNKED) - { - revision.setUnchunked(); - } - - revision.freeze(); - info.setResult(revision); - } - } - - return null; - } - - private InternalCDORevision loadRevisionTarget(CDOID id, CDOBranchPoint branchPoint, int referenceChunk, - IStoreAccessor accessor) - { - CDOBranch branch = branchPoint.getBranch(); - while (!branch.isMainBranch()) - { - branchPoint = branch.getBase(); - branch = branchPoint.getBranch(); - - InternalCDORevision revision = accessor.readRevision(id, branchPoint, referenceChunk, revisionManager); - if (revision != null) - { - revision.freeze(); - return revision; - } - } - - return null; - } - - private long loadRevisionRevised(CDOID id, CDOBranch branch) - { - InternalCDORevision revision = loadRevisionByVersion(id, branch.getVersion(CDORevision.FIRST_VERSION), - CDORevision.UNCHUNKED); - if (revision != null) - { - return revision.getTimeStamp() - 1; - } - - return CDORevision.UNSPECIFIED_DATE; - } - - public InternalCDORevision loadRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk) - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - return accessor.readRevisionByVersion(id, branchVersion, referenceChunk, revisionManager); - } - - /** - * @deprecated Not used. - */ - @Deprecated - protected void ensureChunks(InternalCDORevision revision, int referenceChunk, IStoreAccessor accessor) - { - EClass eClass = revision.getEClass(); - EStructuralFeature[] features = CDOModelUtil.getAllPersistentFeatures(eClass); - for (int i = 0; i < features.length; i++) - { - EStructuralFeature feature = features[i]; - if (feature.isMany()) - { - MoveableList<Object> list = revision.getList(feature); - int chunkEnd = Math.min(referenceChunk, list.size()); - accessor = ensureChunk(revision, feature, accessor, list, 0, chunkEnd); - } - } - } - - public void ensureChunks(InternalCDORevision revision) - { - if (!revision.isUnchunked()) - { - for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(revision.getEClass())) - { - if (feature.isMany()) - { - ensureChunk(revision, feature, 0, revision.getList(feature).size()); - } - } - - revision.setUnchunked(); - } - } - - public IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature, int chunkStart, - int chunkEnd) - { - if (!revision.isUnchunked()) - { - MoveableList<Object> list = revision.getList(feature); - chunkEnd = Math.min(chunkEnd, list.size()); - return ensureChunk(revision, feature, StoreThreadLocal.getAccessor(), list, chunkStart, chunkEnd); - } - - return null; - } - - protected IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature, - IStoreAccessor accessor, MoveableList<Object> list, int chunkStart, int chunkEnd) - { - IStoreChunkReader chunkReader = null; - int fromIndex = -1; - for (int j = chunkStart; j < chunkEnd; j++) - { - if (list.get(j) == InternalCDOList.UNINITIALIZED) - { - if (fromIndex == -1) - { - fromIndex = j; - } - } - else - { - if (fromIndex != -1) - { - if (chunkReader == null) - { - if (accessor == null) - { - accessor = StoreThreadLocal.getAccessor(); - } - - chunkReader = accessor.createChunkReader(revision, feature); - } - - int toIndex = j; - if (fromIndex == toIndex - 1) - { - chunkReader.addSimpleChunk(fromIndex); - } - else - { - chunkReader.addRangedChunk(fromIndex, toIndex); - } - - fromIndex = -1; - } - } - } - - // Add last chunk - if (fromIndex != -1) - { - if (chunkReader == null) - { - if (accessor == null) - { - accessor = StoreThreadLocal.getAccessor(); - } - - chunkReader = accessor.createChunkReader(revision, feature); - } - - int toIndex = chunkEnd; - if (fromIndex == toIndex - 1) - { - chunkReader.addSimpleChunk(fromIndex); - } - else - { - chunkReader.addRangedChunk(fromIndex, toIndex); - } - } - - if (chunkReader != null) - { - InternalCDOList cdoList = list instanceof InternalCDOList ? (InternalCDOList)list : null; - - List<Chunk> chunks = chunkReader.executeRead(); - for (Chunk chunk : chunks) - { - int startIndex = chunk.getStartIndex(); - for (int indexInChunk = 0; indexInChunk < chunk.size(); indexInChunk++) - { - Object id = chunk.get(indexInChunk); - if (cdoList != null) - { - cdoList.setWithoutFrozenCheck(startIndex + indexInChunk, id); - } - else - { - list.set(startIndex + indexInChunk, id); - } - } - } - } - - return accessor; - } - - public InternalCDOPackageRegistry getPackageRegistry(boolean considerCommitContext) - { - if (considerCommitContext) - { - IStoreAccessor.CommitContext commitContext = StoreThreadLocal.getCommitContext(); - if (commitContext != null) - { - InternalCDOPackageRegistry contextualPackageRegistry = commitContext.getPackageRegistry(); - if (contextualPackageRegistry != null) - { - return contextualPackageRegistry; - } - } - } - - return packageRegistry; - } - - public Semaphore getPackageRegistryCommitLock() - { - return packageRegistryCommitLock; - } - - public InternalCDOPackageRegistry getPackageRegistry() - { - return getPackageRegistry(true); - } - - public void setPackageRegistry(InternalCDOPackageRegistry packageRegistry) - { - checkInactive(); - this.packageRegistry = packageRegistry; - } - - public InternalSessionManager getSessionManager() - { - return sessionManager; - } - - /** - * @since 2.0 - */ - public void setSessionManager(InternalSessionManager sessionManager) - { - checkInactive(); - this.sessionManager = sessionManager; - } - - public InternalCDOBranchManager getBranchManager() - { - return branchManager; - } - - public void setBranchManager(InternalCDOBranchManager branchManager) - { - checkInactive(); - this.branchManager = branchManager; - } - - public InternalCDOCommitInfoManager getCommitInfoManager() - { - return commitInfoManager; - } - - public void setCommitInfoManager(InternalCDOCommitInfoManager commitInfoManager) - { - checkInactive(); - this.commitInfoManager = commitInfoManager; - } - - public InternalCDORevisionManager getRevisionManager() - { - return revisionManager; - } - - /** - * @since 2.0 - */ - public void setRevisionManager(InternalCDORevisionManager revisionManager) - { - checkInactive(); - this.revisionManager = revisionManager; - } - - /** - * @since 2.0 - */ - public InternalQueryManager getQueryManager() - { - return queryManager; - } - - /** - * @since 2.0 - */ - public void setQueryManager(InternalQueryManager queryManager) - { - checkInactive(); - this.queryManager = queryManager; - } - - /** - * @since 2.0 - */ - public InternalCommitManager getCommitManager() - { - return commitManager; - } - - /** - * @since 2.0 - */ - public void setCommitManager(InternalCommitManager commitManager) - { - checkInactive(); - this.commitManager = commitManager; - } - - /** - * @since 2.0 - * @deprecated - */ - @Deprecated - public InternalLockManager getLockManager() - { - return getLockingManager(); - } - - public InternalLockManager getLockingManager() - { - return lockingManager; - } - - /** - * @since 2.0 - */ - public void setLockingManager(InternalLockManager lockingManager) - { - checkInactive(); - this.lockingManager = lockingManager; - } - - public InternalCommitContext createCommitContext(InternalTransaction transaction) - { - return new TransactionCommitContext(transaction); - } - - public long getLastCommitTimeStamp() - { - return timeStampAuthority.getLastFinishedTimeStamp(); - } - - public void setLastCommitTimeStamp(long lastCommitTimeStamp) - { - timeStampAuthority.setLastFinishedTimeStamp(lastCommitTimeStamp); - } - - public long waitForCommit(long timeout) - { - return timeStampAuthority.waitForCommit(timeout); - } - - public long[] createCommitTimeStamp(OMMonitor monitor) - { - return timeStampAuthority.startCommit(CDOBranchPoint.UNSPECIFIED_DATE, monitor); - } - - public long[] forceCommitTimeStamp(long override, OMMonitor monitor) - { - return timeStampAuthority.startCommit(override, monitor); - } - - public void endCommit(long timestamp) - { - timeStampAuthority.endCommit(timestamp); - } - - public void failCommit(long timestamp) - { - timeStampAuthority.failCommit(timestamp); - } - - public CDOCommitInfoHandler[] getCommitInfoHandlers() - { - synchronized (commitInfoHandlers) - { - return commitInfoHandlers.toArray(new CDOCommitInfoHandler[commitInfoHandlers.size()]); - } - } - - /** - * @since 4.0 - */ - public void addCommitInfoHandler(CDOCommitInfoHandler handler) - { - synchronized (commitInfoHandlers) - { - if (!commitInfoHandlers.contains(handler)) - { - commitInfoHandlers.add(handler); - } - } - } - - /** - * @since 4.0 - */ - public void removeCommitInfoHandler(CDOCommitInfoHandler handler) - { - synchronized (commitInfoHandlers) - { - commitInfoHandlers.remove(handler); - } - } - - public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo) - { - sessionManager.sendCommitNotification(sender, commitInfo); - - for (CDOCommitInfoHandler handler : getCommitInfoHandlers()) - { - try - { - handler.handleCommitInfo(commitInfo); - } - catch (Exception ex) - { - OM.LOG.error(ex); - } - } - } - - /** - * @since 2.0 - */ - public IQueryHandlerProvider getQueryHandlerProvider() - { - return queryHandlerProvider; - } - - /** - * @since 2.0 - */ - public void setQueryHandlerProvider(IQueryHandlerProvider queryHandlerProvider) - { - this.queryHandlerProvider = queryHandlerProvider; - } - - /** - * @since 2.0 - */ - public synchronized IQueryHandler getQueryHandler(CDOQueryInfo info) - { - String language = info.getQueryLanguage(); - if (CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES.equals(language)) - { - return new ResourcesQueryHandler(); - } - - if (CDOProtocolConstants.QUERY_LANGUAGE_XREFS.equals(language)) - { - return new XRefsQueryHandler(); - } - - IStoreAccessor storeAccessor = StoreThreadLocal.getAccessor(); - if (storeAccessor != null) - { - IQueryHandler handler = storeAccessor.getQueryHandler(info); - if (handler != null) - { - return handler; - } - } - - if (queryHandlerProvider == null) - { - queryHandlerProvider = new ContainerQueryHandlerProvider(IPluginContainer.INSTANCE); - } - - IQueryHandler handler = queryHandlerProvider.getQueryHandler(info); - if (handler != null) - { - return handler; - } - - return null; - } - - public Object[] getElements() - { - final Object[] elements = { packageRegistry, branchManager, revisionManager, sessionManager, queryManager, - commitManager, commitInfoManager, getLockingManager(), store }; - return elements; - } - - @Override - public boolean isEmpty() - { - return false; - } - - /** - * @since 2.0 - */ - public long getCreationTime() - { - return store.getCreationTime(); - } - - /** - * @since 2.0 - */ - public void validateTimeStamp(long timeStamp) throws IllegalArgumentException - { - long creationTimeStamp = getCreationTime(); - if (timeStamp < creationTimeStamp) - { - throw new IllegalArgumentException( - MessageFormat - .format( - "timeStamp ({0}) < repository creation time ({1})", CDOCommonUtil.formatTimeStamp(timeStamp), CDOCommonUtil.formatTimeStamp(creationTimeStamp))); //$NON-NLS-1$ - } - - long currentTimeStamp = getTimeStamp(); - if (timeStamp > currentTimeStamp) - { - throw new IllegalArgumentException( - MessageFormat - .format( - "timeStamp ({0}) > current time ({1})", CDOCommonUtil.formatTimeStamp(timeStamp), CDOCommonUtil.formatTimeStamp(currentTimeStamp))); //$NON-NLS-1$ - } - } - - public long getTimeStamp() - { - return System.currentTimeMillis(); - } - - public Set<Handler> getHandlers() - { - Set<Handler> handlers = new HashSet<Handler>(); - - synchronized (readAccessHandlers) - { - handlers.addAll(readAccessHandlers); - } - - synchronized (writeAccessHandlers) - { - handlers.addAll(writeAccessHandlers); - } - - return handlers; - } - - /** - * @since 2.0 - */ - public void addHandler(Handler handler) - { - if (handler instanceof ReadAccessHandler) - { - synchronized (readAccessHandlers) - { - if (!readAccessHandlers.contains(handler)) - { - readAccessHandlers.add((ReadAccessHandler)handler); - } - } - } - - if (handler instanceof WriteAccessHandler) - { - synchronized (writeAccessHandlers) - { - if (!writeAccessHandlers.contains(handler)) - { - writeAccessHandlers.add((WriteAccessHandler)handler); - } - } - } - } - - /** - * @since 2.0 - */ - public void removeHandler(Handler handler) - { - if (handler instanceof ReadAccessHandler) - { - synchronized (readAccessHandlers) - { - readAccessHandlers.remove(handler); - } - } - - if (handler instanceof WriteAccessHandler) - { - synchronized (writeAccessHandlers) - { - writeAccessHandlers.remove(handler); - } - } - } - - /** - * @since 2.0 - */ - public void notifyReadAccessHandlers(InternalSession session, CDORevision[] revisions, - List<CDORevision> additionalRevisions) - { - ReadAccessHandler[] handlers; - synchronized (readAccessHandlers) - { - int size = readAccessHandlers.size(); - if (size == 0) - { - return; - } - - handlers = readAccessHandlers.toArray(new ReadAccessHandler[size]); - } - - for (ReadAccessHandler handler : handlers) - { - // Do *not* protect against unchecked exceptions from handlers! - handler.handleRevisionsBeforeSending(session, revisions, additionalRevisions); - } - } - - public void notifyWriteAccessHandlers(ITransaction transaction, IStoreAccessor.CommitContext commitContext, - boolean beforeCommit, OMMonitor monitor) - { - WriteAccessHandler[] handlers; - synchronized (writeAccessHandlers) - { - int size = writeAccessHandlers.size(); - if (size == 0) - { - return; - } - - handlers = writeAccessHandlers.toArray(new WriteAccessHandler[size]); - } - - try - { - monitor.begin(handlers.length); - for (WriteAccessHandler handler : handlers) - { - try - { - if (beforeCommit) - { - handler.handleTransactionBeforeCommitting(transaction, commitContext, monitor.fork()); - } - else - { - handler.handleTransactionAfterCommitted(transaction, commitContext, monitor.fork()); - } - } - catch (RuntimeException ex) - { - if (!beforeCommit) - { - OM.LOG.error(ex); - } - else - { - // Do *not* protect against unchecked exceptions from handlers on before case! - throw ex; - } - } - } - } - finally - { - monitor.done(); - } - } - - public void setInitialPackages(EPackage... initialPackages) - { - checkInactive(); - this.initialPackages = initialPackages; - } - - public CDOReplicationInfo replicateRaw(CDODataOutput out, int lastReplicatedBranchID, long lastReplicatedCommitTime) - throws IOException - { - final int fromBranchID = lastReplicatedBranchID + 1; - final int toBranchID = getStore().getLastBranchID(); - - final long fromCommitTime = lastReplicatedCommitTime + 1L; - final long toCommitTime = getStore().getLastCommitTime(); - - out.writeInt(toBranchID); - out.writeLong(toCommitTime); - - IStoreAccessor.Raw accessor = (IStoreAccessor.Raw)StoreThreadLocal.getAccessor(); - accessor.rawExport(out, fromBranchID, toBranchID, fromCommitTime, toCommitTime); - - return new CDOReplicationInfo() - { - public int getLastReplicatedBranchID() - { - return toBranchID; - } - - public long getLastReplicatedCommitTime() - { - return toCommitTime; - } - - public String[] getLockAreaIDs() - { - return null; // TODO (CD) Raw replication of lockAreas - } - }; - } - - public void replicate(CDOReplicationContext context) - { - int startID = context.getLastReplicatedBranchID() + 1; - branchManager.getBranches(startID, 0, context); - - long startTime = context.getLastReplicatedCommitTime(); - commitInfoManager.getCommitInfos(null, startTime + 1L, CDOBranchPoint.UNSPECIFIED_DATE, context); - - getLockingManager().getLockAreas(null, context); - } - - public CDOChangeSetData getChangeSet(CDOBranchPoint startPoint, CDOBranchPoint endPoint) - { - CDOChangeSetSegment[] segments = CDOChangeSetSegment.createFrom(startPoint, endPoint); - - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - Set<CDOID> ids = accessor.readChangeSet(new Monitor(), segments); - - return CDORevisionUtil.createChangeSetData(ids, startPoint, endPoint, revisionManager); - } - - public Set<CDOID> getMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, - CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor) - { - CDOBranchPoint target = targetInfo.getBranchPoint(); - CDOBranchPoint source = sourceInfo.getBranchPoint(); - - monitor.begin(5); - - try - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - Set<CDOID> ids = new HashSet<CDOID>(); - - if (targetBaseInfo == null && sourceBaseInfo == null) - { - if (CDOBranchUtil.isContainedBy(source, target)) - { - ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(source, target))); - } - else if (CDOBranchUtil.isContainedBy(target, source)) - { - ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(target, source))); - } - else - { - CDOBranchPoint ancestor = CDOBranchUtil.getAncestor(target, source); - ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(ancestor, target))); - ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(ancestor, source))); - } - } - else - { - CDORevisionAvailabilityInfo sourceBaseInfoToUse = sourceBaseInfo == null ? targetBaseInfo : sourceBaseInfo; - - ids.addAll(accessor.readChangeSet(monitor.fork(), - CDOChangeSetSegment.createFrom(targetBaseInfo.getBranchPoint(), target))); - - ids.addAll(accessor.readChangeSet(monitor.fork(), - CDOChangeSetSegment.createFrom(sourceBaseInfoToUse.getBranchPoint(), source))); - } - - loadMergeData(ids, targetInfo, monitor.fork()); - loadMergeData(ids, sourceInfo, monitor.fork()); - - if (targetBaseInfo != null) - { - loadMergeData(ids, targetBaseInfo, monitor.fork()); - } - - if (sourceBaseInfo != null) - { - loadMergeData(ids, sourceBaseInfo, monitor.fork()); - } - - return ids; - } - finally - { - monitor.done(); - } - } - - private void loadMergeData(Set<CDOID> ids, CDORevisionAvailabilityInfo info, OMMonitor monitor) - { - int size = ids.size(); - monitor.begin(size); - - try - { - CDOBranchPoint branchPoint = info.getBranchPoint(); - for (CDOID id : ids) - { - if (info.containsRevision(id)) - { - info.removeRevision(id); - } - else - { - InternalCDORevision revision = getRevisionFromBranch(id, branchPoint); - if (revision != null) - { - info.addRevision(revision); - } - else - { - info.removeRevision(id); - } - } - - monitor.worked(); - } - } - finally - { - monitor.done(); - } - } - - private InternalCDORevision getRevisionFromBranch(CDOID id, CDOBranchPoint branchPoint) - { - InternalCDORevision revision = revisionManager.getRevision(id, branchPoint, CDORevision.UNCHUNKED, - CDORevision.DEPTH_NONE, true); - // if (revision == null || !ObjectUtil.equals(revision.getBranch(), branchPoint.getBranch())) - // { - // return null; - // } - - return revision; - } - - public void queryLobs(List<byte[]> ids) - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - accessor.queryLobs(ids); - } - - public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - accessor.handleLobs(fromTime, toTime, handler); - } - - public void loadLob(byte[] id, OutputStream out) throws IOException - { - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - accessor.loadLob(id, out); - } - - public void handleRevisions(EClass eClass, CDOBranch branch, boolean exactBranch, long timeStamp, boolean exactTime, - final CDORevisionHandler handler) - { - CDORevisionHandler wrapper = handler; - if (!exactBranch && !branch.isMainBranch()) - { - if (exactTime && timeStamp == CDOBranchPoint.UNSPECIFIED_DATE) - { - throw new IllegalArgumentException("Time stamp must be specified if exactBranch==false and exactTime==true"); - } - - wrapper = new CDORevisionHandler() - { - private Set<CDOID> handled = new HashSet<CDOID>(); - - public boolean handleRevision(CDORevision revision) - { - CDOID id = revision.getID(); - if (handled.add(id)) - { - return handler.handleRevision(revision); - } - - return true; - } - }; - } - - IStoreAccessor accessor = StoreThreadLocal.getAccessor(); - while (branch != null) - { - accessor.handleRevisions(eClass, branch, timeStamp, exactTime, wrapper); - if (exactBranch) - { - break; - } - - CDOBranchPoint base = branch.getBase(); - branch = base.getBranch(); - timeStamp = base.getTimeStamp(); - } - } - - public static List<Object> revisionKeysToObjects(List<CDORevisionKey> revisionKeys, CDOBranch viewedBranch, - boolean isSupportingBranches) - { - List<Object> lockables = new ArrayList<Object>(); - for (CDORevisionKey revKey : revisionKeys) - { - CDOID id = revKey.getID(); - if (isSupportingBranches) - { - lockables.add(CDOIDUtil.createIDAndBranch(id, viewedBranch)); - } - else - { - lockables.add(id); - } - } - return lockables; - } - - public LockObjectsResult lock(InternalView view, LockType lockType, List<CDORevisionKey> revKeys, boolean recursive, - long timeout) - { - List<Object> lockables = revisionKeysToObjects(revKeys, view.getBranch(), isSupportingBranches()); - return lock(view, lockType, lockables, revKeys, recursive, timeout); - } - - protected LockObjectsResult lock(InternalView view, LockType type, List<Object> lockables, - List<CDORevisionKey> loadedRevs, boolean recursive, long timeout) - { - List<LockState<Object, IView>> newLockStates = null; - try - { - newLockStates = getLockingManager().lock2(true, type, view, lockables, recursive, timeout); - } - catch (TimeoutRuntimeException ex) - { - return new LockObjectsResult(false, true, false, 0, new CDORevisionKey[0], new CDOLockState[0], getTimeStamp()); - } - catch (InterruptedException ex) - { - throw WrappedException.wrap(ex); - } - - long[] requiredTimestamp = { 0L }; - CDORevisionKey[] staleRevisionsArray = null; - - try - { - staleRevisionsArray = checkStaleRevisions(view, loadedRevs, lockables, type, requiredTimestamp); - } - catch (IllegalArgumentException e) - { - getLockingManager().unlock2(true, type, view, lockables, recursive); - throw e; - } - - // If some of the clients' revisions are stale and it has passiveUpdates disabled, - // then the locks are useless so we release them and report the stale revisions - // - InternalSession session = view.getSession(); - boolean staleNoUpdate = staleRevisionsArray.length > 0 && !session.isPassiveUpdateEnabled(); - if (staleNoUpdate) - { - getLockingManager().unlock2(true, type, view, lockables, recursive); - return new LockObjectsResult(false, false, false, requiredTimestamp[0], staleRevisionsArray, new CDOLockState[0], - getTimeStamp()); - } - - CDOLockState[] cdoLockStates = toCDOLockStates(newLockStates); - sendLockNotifications(view, Operation.LOCK, type, cdoLockStates); - - boolean waitForUpdate = staleRevisionsArray.length > 0; - return new LockObjectsResult(true, false, waitForUpdate, requiredTimestamp[0], staleRevisionsArray, cdoLockStates, - getTimeStamp()); - } - - private CDORevisionKey[] checkStaleRevisions(InternalView view, List<CDORevisionKey> revisionKeys, - List<Object> objectsToLock, LockType lockType, long[] requiredTimestamp) - { - List<CDORevisionKey> staleRevisions = new LinkedList<CDORevisionKey>(); - if (revisionKeys != null) - { - InternalCDORevisionManager revManager = getRevisionManager(); - CDOBranch viewedBranch = view.getBranch(); - for (CDORevisionKey revKey : revisionKeys) - { - CDOID id = revKey.getID(); - InternalCDORevision rev = revManager.getRevision(id, viewedBranch.getHead(), CDORevision.UNCHUNKED, - CDORevision.DEPTH_NONE, true); - - if (rev == null) - { - throw new IllegalArgumentException(String.format("Object %s not found in branch %s (possibly detached)", id, - viewedBranch)); - } - - if (!revKey.equals(rev)) - { - staleRevisions.add(revKey); - requiredTimestamp[0] = Math.max(requiredTimestamp[0], rev.getTimeStamp()); - } - } - } - - // Convert the list to an array, to satisfy the API later - // - CDORevisionKey[] staleRevisionsArray = new CDORevisionKey[staleRevisions.size()]; - staleRevisions.toArray(staleRevisionsArray); - - return staleRevisionsArray; - } - - private void sendLockNotifications(IView view, Operation operation, LockType lockType, CDOLockState[] cdoLockStates) - { - long timestamp = getTimeStamp(); - CDOLockChangeInfo lockChangeInfo = CDOLockUtil.createLockChangeInfo(timestamp, view, view.getBranch(), operation, - lockType, cdoLockStates); - getSessionManager().sendLockNotification((InternalSession)view.getSession(), lockChangeInfo); - } - - // TODO (CD) This doesn't really belong here.. but getting it into CDOLockUtil isn't possible - public static CDOLockState[] toCDOLockStates(List<LockState<Object, IView>> lockStates) - { - CDOLockState[] cdoLockStates = new CDOLockState[lockStates.size()]; - int i = 0; - - for (LockState<Object, ? extends CDOCommonView> lockState : lockStates) - { - CDOLockState cdoLockState = CDOLockUtil.createLockState(lockState); - cdoLockStates[i++] = cdoLockState; - } - - return cdoLockStates; - } - - public UnlockObjectsResult unlock(InternalView view, LockType lockType, List<CDOID> objectIDs, boolean recursive) - { - List<Object> unlockables = null; - if (objectIDs != null) - { - unlockables = new ArrayList<Object>(objectIDs.size()); - CDOBranch branch = view.getBranch(); - for (CDOID id : objectIDs) - { - Object key = supportingBranches ? CDOIDUtil.createIDAndBranch(id, branch) : id; - unlockables.add(key); - } - } - - return doUnlock(view, lockType, unlockables, recursive); - } - - protected UnlockObjectsResult doUnlock(InternalView view, LockType lockType, List<Object> unlockables, - boolean recursive) - { - List<LockState<Object, IView>> newLockStates = null; - if (lockType == null) // Signals an unlock-all operation - { - newLockStates = getLockingManager().unlock2(true, view); - } - else - { - newLockStates = getLockingManager().unlock2(true, lockType, view, unlockables, recursive); - } - - long timestamp = getTimeStamp(); - CDOLockState[] cdoLockStates = toCDOLockStates(newLockStates); - sendLockNotifications(view, Operation.UNLOCK, lockType, cdoLockStates); - - return new UnlockObjectsResult(cdoLockStates, timestamp); - } - - @Override - public String toString() - { - return MessageFormat.format("Repository[{0}]", name); //$NON-NLS-1$ - } - - public boolean isSkipInitialization() - { - return skipInitialization; - } - - public void setSkipInitialization(boolean skipInitialization) - { - this.skipInitialization = skipInitialization; - } - - protected void initProperties() - { - String valueAudits = properties.get(Props.SUPPORTING_AUDITS); - if (valueAudits != null) - { - supportingAudits = Boolean.valueOf(valueAudits); - } - else - { - supportingAudits = store.getRevisionTemporality() == IStore.RevisionTemporality.AUDITING; - } - - String valueBranches = properties.get(Props.SUPPORTING_BRANCHES); - if (valueBranches != null) - { - supportingBranches = Boolean.valueOf(valueBranches); - } - else - { - supportingBranches = store.getRevisionParallelism() == IStore.RevisionParallelism.BRANCHING; - } - - String valueEcore = properties.get(Props.SUPPORTING_ECORE); - if (valueEcore != null) - { - supportingEcore = Boolean.valueOf(valueEcore); - } - - String valueIntegrity = properties.get(Props.ENSURE_REFERENTIAL_INTEGRITY); - if (valueIntegrity != null) - { - ensuringReferentialIntegrity = Boolean.valueOf(valueIntegrity); - } - - String valueIDLocation = properties.get(Props.ID_GENERATION_LOCATION); - if (valueIDLocation != null) - { - idGenerationLocation = IDGenerationLocation.valueOf(valueIDLocation); - } - - if (idGenerationLocation == null) - { - idGenerationLocation = IDGenerationLocation.STORE; - } - } - - public void initSystemPackages() - { - IStoreAccessor writer = store.getWriter(null); - StoreThreadLocal.setAccessor(writer); - - try - { - List<InternalCDOPackageUnit> units = new ArrayList<InternalCDOPackageUnit>(); - units.add(initSystemPackage(EcorePackage.eINSTANCE)); - units.add(initSystemPackage(EresourcePackage.eINSTANCE)); - units.add(initSystemPackage(EtypesPackage.eINSTANCE)); - - if (initialPackages != null) - { - for (EPackage initialPackage : initialPackages) - { - if (!packageRegistry.containsKey(initialPackage.getNsURI())) - { - units.add(initSystemPackage(initialPackage)); - } - } - } - - InternalCDOPackageUnit[] systemUnits = units.toArray(new InternalCDOPackageUnit[units.size()]); - writer.writePackageUnits(systemUnits, new Monitor()); - writer.commit(new Monitor()); - } - finally - { - StoreThreadLocal.release(); - } - } - - protected InternalCDOPackageUnit initSystemPackage(EPackage ePackage) - { - EMFUtil.registerPackage(ePackage, packageRegistry); - InternalCDOPackageInfo packageInfo = packageRegistry.getPackageInfo(ePackage); - - InternalCDOPackageUnit packageUnit = packageInfo.getPackageUnit(); - packageUnit.setTimeStamp(store.getCreationTime()); - packageUnit.setState(CDOPackageUnit.State.LOADED); - return packageUnit; - } - - public void initMainBranch(InternalCDOBranchManager branchManager, long timeStamp) - { - branchManager.initMainBranch(false, timeStamp); - } - - protected void initRootResource() - { - CDOBranchPoint head = branchManager.getMainBranch().getHead(); - - CDORevisionFactory factory = getRevisionManager().getFactory(); - InternalCDORevision rootResource = (InternalCDORevision)factory - .createRevision(EresourcePackage.Literals.CDO_RESOURCE); - - rootResource.setBranchPoint(head); - rootResource.setContainerID(CDOID.NULL); - rootResource.setContainingFeatureID(0); - - CDOID id = createRootResourceID(); - rootResource.setID(id); - rootResource.setResourceID(id); - - InternalSession session = getSessionManager().openSession(null); - InternalTransaction transaction = session.openTransaction(1, head); - InternalCommitContext commitContext = new TransactionCommitContext(transaction) - { - @Override - protected long[] createTimeStamp(OMMonitor monitor) - { - InternalRepository repository = getTransaction().getSession().getManager().getRepository(); - return repository.forceCommitTimeStamp(store.getCreationTime(), monitor); - } - - @Override - public String getUserID() - { - return SYSTEM_USER_ID; - } - - @Override - public String getCommitComment() - { - return "<initialize>"; //$NON-NLS-1$ - } - }; - - commitContext.setNewObjects(new InternalCDORevision[] { rootResource }); - commitContext.preWrite(); - - commitContext.write(new Monitor()); - commitContext.commit(new Monitor()); - - String rollbackMessage = commitContext.getRollbackMessage(); - if (rollbackMessage != null) - { - throw new TransactionException(rollbackMessage); - } - - rootResourceID = id instanceof CDOIDTemp ? commitContext.getIDMappings().get(id) : id; - - commitContext.postCommit(true); - session.close(); - } - - protected CDOID createRootResourceID() - { - if (getIDGenerationLocation() == IDGenerationLocation.STORE) - { - return CDOIDUtil.createTempObject(1); - } - - return CDOIDGenerator.UUID.generateCDOID(null); - } - - protected void readRootResource() - { - IStoreAccessor reader = store.getReader(null); - StoreThreadLocal.setAccessor(reader); - - try - { - CDOBranchPoint head = branchManager.getMainBranch().getHead(); - rootResourceID = reader.readResourceID(CDOID.NULL, null, head); - } - finally - { - StoreThreadLocal.release(); - } - } - - protected void readPackageUnits() - { - IStoreAccessor reader = store.getReader(null); - StoreThreadLocal.setAccessor(reader); - - try - { - Collection<InternalCDOPackageUnit> packageUnits = reader.readPackageUnits(); - for (InternalCDOPackageUnit packageUnit : packageUnits) - { - packageRegistry.putPackageUnit(packageUnit); - } - } - finally - { - StoreThreadLocal.release(); - } - } - - @Override - protected void doBeforeActivate() throws Exception - { - super.doBeforeActivate(); - checkState(store, "store"); //$NON-NLS-1$ - checkState(!StringUtil.isEmpty(name), "name is empty"); //$NON-NLS-1$ - checkState(packageRegistry, "packageRegistry"); //$NON-NLS-1$ - checkState(sessionManager, "sessionManager"); //$NON-NLS-1$ - checkState(branchManager, "branchManager"); //$NON-NLS-1$ - checkState(revisionManager, "revisionManager"); //$NON-NLS-1$ - checkState(queryManager, "queryManager"); //$NON-NLS-1$ - checkState(commitInfoManager, "commitInfoManager"); //$NON-NLS-1$ - checkState(commitManager, "commitManager"); //$NON-NLS-1$ - checkState(getLockingManager(), "lockingManager"); //$NON-NLS-1$ - - packageRegistry.setReplacingDescriptors(true); - packageRegistry.setPackageProcessor(this); - packageRegistry.setPackageLoader(this); - - branchManager.setBranchLoader(this); - branchManager.setTimeProvider(this); - - revisionManager.setRevisionLoader(this); - sessionManager.setRepository(this); - queryManager.setRepository(this); - commitInfoManager.setCommitInfoLoader(this); - commitManager.setRepository(this); - getLockingManager().setRepository(this); - store.setRepository(this); - } - - @Override - protected void doActivate() throws Exception - { - super.doActivate(); - - initProperties(); - if (idGenerationLocation == IDGenerationLocation.CLIENT && !(store instanceof CanHandleClientAssignedIDs)) - { - throw new IllegalStateException("Store can not handle client assigned IDs: " + store); - } - - store.setRevisionTemporality(supportingAudits ? IStore.RevisionTemporality.AUDITING - : IStore.RevisionTemporality.NONE); - store.setRevisionParallelism(supportingBranches ? IStore.RevisionParallelism.BRANCHING - : IStore.RevisionParallelism.NONE); - revisionManager.setSupportingAudits(supportingAudits); - revisionManager.setSupportingBranches(supportingBranches); - - LifecycleUtil.activate(store); - LifecycleUtil.activate(packageRegistry); - LifecycleUtil.activate(sessionManager); - LifecycleUtil.activate(revisionManager); - LifecycleUtil.activate(branchManager); - LifecycleUtil.activate(queryManager); - LifecycleUtil.activate(commitInfoManager); - LifecycleUtil.activate(commitManager); - LifecycleUtil.activate(queryHandlerProvider); - - if (!skipInitialization) - { - long lastCommitTimeStamp = Math.max(store.getCreationTime(), store.getLastCommitTime()); - timeStampAuthority.setLastFinishedTimeStamp(lastCommitTimeStamp); - initMainBranch(branchManager, lastCommitTimeStamp); - - if (store.isFirstStart()) - { - initSystemPackages(); - initRootResource(); - } - else - { - readPackageUnits(); - readRootResource(); - } - - // This check does not work for CDOWorkspace: - // if (CDOIDUtil.isNull(rootResourceID)) - // { - // throw new IllegalStateException("Root resource ID is null"); - // } - } - - LifecycleUtil.activate(getLockingManager()); // Needs an initialized main branch / branch manager - } - - @Override - protected void doDeactivate() throws Exception - { - LifecycleUtil.deactivate(getLockingManager()); - LifecycleUtil.deactivate(queryHandlerProvider); - LifecycleUtil.deactivate(commitManager); - LifecycleUtil.deactivate(commitInfoManager); - LifecycleUtil.deactivate(queryManager); - LifecycleUtil.deactivate(revisionManager); - LifecycleUtil.deactivate(sessionManager); - LifecycleUtil.deactivate(store); - LifecycleUtil.deactivate(branchManager); - LifecycleUtil.deactivate(packageRegistry); - super.doDeactivate(); - } - - /** - * @author Eike Stepper - * @since 2.0 - */ - public static class Default extends Repository - { - public Default() - { - } - - @Override - protected void doBeforeActivate() throws Exception - { - if (getPackageRegistry(false) == null) - { - setPackageRegistry(createPackageRegistry()); - } - - if (getSessionManager() == null) - { - setSessionManager(createSessionManager()); - } - - if (getBranchManager() == null) - { - setBranchManager(createBranchManager()); - } - - if (getRevisionManager() == null) - { - setRevisionManager(createRevisionManager()); - } - - if (getQueryManager() == null) - { - setQueryManager(createQueryManager()); - } - - if (getCommitInfoManager() == null) - { - setCommitInfoManager(createCommitInfoManager()); - } - - if (getCommitManager() == null) - { - setCommitManager(createCommitManager()); - } - - if (getLockManager() == null) - { - setLockingManager(createLockManager()); - } - - super.doBeforeActivate(); - } - - protected InternalCDOPackageRegistry createPackageRegistry() - { - return new CDOPackageRegistryImpl(); - } - - protected InternalSessionManager createSessionManager() - { - return new SessionManager(); - } - - protected InternalCDOBranchManager createBranchManager() - { - return CDOBranchUtil.createBranchManager(); - } - - protected InternalCDORevisionManager createRevisionManager() - { - return (InternalCDORevisionManager)CDORevisionUtil.createRevisionManager(); - } - - protected InternalQueryManager createQueryManager() - { - return new QueryManager(); - } - - protected InternalCDOCommitInfoManager createCommitInfoManager() - { - return CDOCommitInfoUtil.createCommitInfoManager(); - } - - protected InternalCommitManager createCommitManager() - { - return new CommitManager(); - } - - @Deprecated - protected InternalLockManager createLockManager() - { - return createLockingManager(); - } - - public LockingManager createLockingManager() - { - return new LockingManager(); - } - } -} +/*
+ * 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 233273
+ * Simon McDuff - bug 233490
+ * Stefan Winkler - changed order of determining audit and revision delta support.
+ * Andre Dietisheim - bug 256649
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonView;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
+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.CDOCommitInfoHandler;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDGenerator;
+import org.eclipse.emf.cdo.common.id.CDOIDTemp;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+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.model.EMFUtil;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionFactory;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.common.util.RepositoryStateChangedEvent;
+import org.eclipse.emf.cdo.common.util.RepositoryTypeChangedEvent;
+import org.eclipse.emf.cdo.eresource.EresourcePackage;
+import org.eclipse.emf.cdo.etypes.EtypesPackage;
+import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl;
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.IQueryHandlerProvider;
+import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.server.IStore.CanHandleClientAssignedIDs;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreChunkReader;
+import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.common.CDOReplicationContext;
+import org.eclipse.emf.cdo.spi.common.CDOReplicationInfo;
+import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+import org.eclipse.emf.cdo.spi.common.commit.CDOCommitInfoUtil;
+import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo;
+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.DetachedCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo;
+import org.eclipse.emf.cdo.spi.server.ContainerQueryHandlerProvider;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalCommitManager;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
+import org.eclipse.emf.cdo.spi.server.InternalQueryManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalSessionManager;
+import org.eclipse.emf.cdo.spi.server.InternalStore;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+
+import org.eclipse.emf.internal.cdo.object.CDOFactoryImpl;
+
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.collection.MoveableList;
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
+import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
+import org.eclipse.net4j.util.container.Container;
+import org.eclipse.net4j.util.container.IPluginContainer;
+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.net4j.util.transaction.TransactionException;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.LockObjectsResult;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.UnlockObjectsResult;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+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.UUID;
+import java.util.concurrent.Semaphore;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class Repository extends Container<Object> implements InternalRepository
+{
+ private String name;
+
+ private String uuid;
+
+ private InternalStore store;
+
+ private Type type = Type.MASTER;
+
+ private State state = State.ONLINE;
+
+ private Map<String, String> properties;
+
+ private boolean supportingAudits;
+
+ private boolean supportingBranches;
+
+ private boolean supportingEcore;
+
+ private boolean ensuringReferentialIntegrity;
+
+ private IDGenerationLocation idGenerationLocation;
+
+ /**
+ * Must not be thread-bound to support XA commits.
+ */
+ private Semaphore packageRegistryCommitLock = new Semaphore(1);
+
+ private InternalCDOPackageRegistry packageRegistry;
+
+ private InternalCDOBranchManager branchManager;
+
+ private InternalCDORevisionManager revisionManager;
+
+ private InternalCDOCommitInfoManager commitInfoManager;
+
+ private InternalSessionManager sessionManager;
+
+ private InternalQueryManager queryManager;
+
+ private InternalCommitManager commitManager;
+
+ private InternalLockManager lockingManager;
+
+ private IQueryHandlerProvider queryHandlerProvider;
+
+ private List<ReadAccessHandler> readAccessHandlers = new ArrayList<ReadAccessHandler>();
+
+ private List<WriteAccessHandler> writeAccessHandlers = new ArrayList<WriteAccessHandler>();
+
+ private List<CDOCommitInfoHandler> commitInfoHandlers = new ArrayList<CDOCommitInfoHandler>();
+
+ private EPackage[] initialPackages;
+
+ // Bugzilla 297940
+ private TimeStampAuthority timeStampAuthority = new TimeStampAuthority(this);
+
+ @ExcludeFromDump
+ private transient Object createBranchLock = new Object();
+
+ private boolean skipInitialization;
+
+ private CDOID rootResourceID;
+
+ public Repository()
+ {
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getUUID()
+ {
+ if (uuid == null)
+ {
+ uuid = getProperties().get(Props.OVERRIDE_UUID);
+ if (uuid == null)
+ {
+ uuid = UUID.randomUUID().toString();
+ }
+ else if (uuid.length() == 0)
+ {
+ uuid = getName();
+ }
+ }
+
+ return uuid;
+ }
+
+ public InternalStore getStore()
+ {
+ return store;
+ }
+
+ public void setStore(InternalStore store)
+ {
+ this.store = store;
+ }
+
+ public Type getType()
+ {
+ return type;
+ }
+
+ public void setType(Type type)
+ {
+ checkArg(type, "type"); //$NON-NLS-1$
+ if (this.type != type)
+ {
+ changingType(this.type, type);
+ }
+ }
+
+ protected void changingType(Type oldType, Type newType)
+ {
+ type = newType;
+ fireEvent(new RepositoryTypeChangedEvent(this, oldType, newType));
+
+ if (sessionManager != null)
+ {
+ sessionManager.sendRepositoryTypeNotification(oldType, newType);
+ }
+ }
+
+ public State getState()
+ {
+ return state;
+ }
+
+ public void setState(State state)
+ {
+ checkArg(state, "state"); //$NON-NLS-1$
+ if (this.state != state)
+ {
+ changingState(this.state, state);
+ }
+ }
+
+ protected void changingState(State oldState, State newState)
+ {
+ state = newState;
+ fireEvent(new RepositoryStateChangedEvent(this, oldState, newState));
+
+ if (sessionManager != null)
+ {
+ sessionManager.sendRepositoryStateNotification(oldState, newState, getRootResourceID());
+ }
+ }
+
+ public synchronized Map<String, String> getProperties()
+ {
+ if (properties == null)
+ {
+ properties = new HashMap<String, String>();
+ }
+
+ return properties;
+ }
+
+ public synchronized void setProperties(Map<String, String> properties)
+ {
+ this.properties = properties;
+ }
+
+ public boolean isSupportingAudits()
+ {
+ return supportingAudits;
+ }
+
+ public boolean isSupportingBranches()
+ {
+ return supportingBranches;
+ }
+
+ public boolean isSupportingEcore()
+ {
+ return supportingEcore;
+ }
+
+ public boolean isEnsuringReferentialIntegrity()
+ {
+ return ensuringReferentialIntegrity;
+ }
+
+ public IDGenerationLocation getIDGenerationLocation()
+ {
+ return idGenerationLocation;
+ }
+
+ public String getStoreType()
+ {
+ return store.getType();
+ }
+
+ public Set<CDOID.ObjectType> getObjectIDTypes()
+ {
+ return store.getObjectIDTypes();
+ }
+
+ public CDOID getRootResourceID()
+ {
+ return rootResourceID;
+ }
+
+ public void setRootResourceID(CDOID rootResourceID)
+ {
+ this.rootResourceID = rootResourceID;
+ }
+
+ public Object processPackage(Object value)
+ {
+ CDOFactoryImpl.prepareDynamicEPackage(value);
+ return value;
+ }
+
+ public EPackage[] loadPackages(CDOPackageUnit packageUnit)
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ return accessor.loadPackageUnit((InternalCDOPackageUnit)packageUnit);
+ }
+
+ public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo)
+ {
+ if (!isSupportingBranches())
+ {
+ throw new IllegalStateException("Branching is not supported by " + this);
+ }
+
+ long baseTimeStamp = branchInfo.getBaseTimeStamp();
+ if (baseTimeStamp == CDOBranchPoint.UNSPECIFIED_DATE)
+ {
+ baseTimeStamp = getTimeStamp();
+ branchInfo = new BranchInfo(branchInfo.getName(), branchInfo.getBaseBranchID(), baseTimeStamp);
+ }
+
+ synchronized (createBranchLock)
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ return accessor.createBranch(branchID, branchInfo);
+ }
+ }
+
+ public BranchInfo loadBranch(int branchID)
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ return accessor.loadBranch(branchID);
+ }
+
+ public SubBranchInfo[] loadSubBranches(int branchID)
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ return accessor.loadSubBranches(branchID);
+ }
+
+ public int loadBranches(int startID, int endID, CDOBranchHandler branchHandler)
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ return accessor.loadBranches(startID, endID, branchHandler);
+ }
+
+ public void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler)
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ accessor.loadCommitInfos(branch, startTime, endTime, handler);
+ }
+
+ public CDOCommitData loadCommitData(long timeStamp)
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ return accessor.loadCommitData(timeStamp);
+ }
+
+ public List<InternalCDORevision> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint,
+ int referenceChunk, int prefetchDepth)
+ {
+ for (RevisionInfo info : infos)
+ {
+ CDOID id = info.getID();
+ RevisionInfo.Type type = info.getType();
+ switch (type)
+ {
+ case AVAILABLE_NORMAL: // direct == false
+ {
+ RevisionInfo.Available.Normal availableInfo = (RevisionInfo.Available.Normal)info;
+ checkArg(availableInfo.isDirect() == false, "Load is not needed");
+ break;
+ }
+
+ case AVAILABLE_POINTER: // direct == false || target == null
+ {
+ RevisionInfo.Available.Pointer pointerInfo = (RevisionInfo.Available.Pointer)info;
+ boolean needsTarget = !pointerInfo.hasTarget();
+ checkArg(pointerInfo.isDirect() == false || needsTarget, "Load is not needed");
+
+ if (needsTarget)
+ {
+ CDOBranchVersion targetBranchVersion = pointerInfo.getTargetBranchVersion();
+ InternalCDORevision target = loadRevisionByVersion(id, targetBranchVersion, referenceChunk);
+ PointerCDORevision pointer = new PointerCDORevision(target.getEClass(), id, pointerInfo
+ .getAvailableBranchVersion().getBranch(), CDORevision.UNSPECIFIED_DATE, target);
+
+ info.setResult(target);
+ info.setSynthetic(pointer);
+ continue;
+ }
+
+ break;
+ }
+
+ case AVAILABLE_DETACHED: // direct == false
+ {
+ RevisionInfo.Available.Detached detachedInfo = (RevisionInfo.Available.Detached)info;
+ checkArg(detachedInfo.isDirect() == false, "Load is not needed");
+ break;
+ }
+
+ case MISSING:
+ {
+ break;
+ }
+
+ default:
+ throw new IllegalStateException("Invalid revision info type: " + type);
+ }
+
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ InternalCDORevision revision = accessor.readRevision(id, branchPoint, referenceChunk, revisionManager);
+ if (revision == null)
+ {
+ if (isSupportingAudits())
+ {
+ // Case "Pointer"?
+ InternalCDORevision target = loadRevisionTarget(id, branchPoint, referenceChunk, accessor);
+ if (target != null)
+ {
+ CDOBranch branch = branchPoint.getBranch();
+ long revised = loadRevisionRevised(id, branch);
+ PointerCDORevision pointer = new PointerCDORevision(target.getEClass(), id, branch, revised, target);
+ info.setSynthetic(pointer);
+ }
+
+ info.setResult(target);
+ }
+ else
+ {
+ DetachedCDORevision detachedRevision = new DetachedCDORevision(EcorePackage.Literals.ECLASS, id,
+ branchPoint.getBranch(), 0, CDORevision.UNSPECIFIED_DATE);
+ info.setSynthetic(detachedRevision);
+ }
+ }
+ else if (revision instanceof DetachedCDORevision)
+ {
+ DetachedCDORevision detached = (DetachedCDORevision)revision;
+ info.setSynthetic(detached);
+ }
+ else
+ {
+ revision.freeze();
+ info.setResult(revision);
+ }
+ }
+
+ return null;
+ }
+
+ private InternalCDORevision loadRevisionTarget(CDOID id, CDOBranchPoint branchPoint, int referenceChunk,
+ IStoreAccessor accessor)
+ {
+ CDOBranch branch = branchPoint.getBranch();
+ while (!branch.isMainBranch())
+ {
+ branchPoint = branch.getBase();
+ branch = branchPoint.getBranch();
+
+ InternalCDORevision revision = accessor.readRevision(id, branchPoint, referenceChunk, revisionManager);
+ if (revision != null)
+ {
+ revision.freeze();
+ return revision;
+ }
+ }
+
+ return null;
+ }
+
+ private long loadRevisionRevised(CDOID id, CDOBranch branch)
+ {
+ InternalCDORevision revision = loadRevisionByVersion(id, branch.getVersion(CDORevision.FIRST_VERSION),
+ CDORevision.UNCHUNKED);
+ if (revision != null)
+ {
+ return revision.getTimeStamp() - 1;
+ }
+
+ return CDORevision.UNSPECIFIED_DATE;
+ }
+
+ public InternalCDORevision loadRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk)
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ return accessor.readRevisionByVersion(id, branchVersion, referenceChunk, revisionManager);
+ }
+
+ protected void ensureChunks(InternalCDORevision revision, int referenceChunk, IStoreAccessor accessor)
+ {
+ EClass eClass = revision.getEClass();
+ EStructuralFeature[] features = CDOModelUtil.getAllPersistentFeatures(eClass);
+ for (int i = 0; i < features.length; i++)
+ {
+ EStructuralFeature feature = features[i];
+ if (feature.isMany())
+ {
+ MoveableList<Object> list = revision.getList(feature);
+ int chunkEnd = Math.min(referenceChunk, list.size());
+ accessor = ensureChunk(revision, feature, accessor, list, 0, chunkEnd);
+ }
+ }
+ }
+
+ public IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature, int chunkStart,
+ int chunkEnd)
+ {
+ MoveableList<Object> list = revision.getList(feature);
+ chunkEnd = Math.min(chunkEnd, list.size());
+ return ensureChunk(revision, feature, StoreThreadLocal.getAccessor(), list, chunkStart, chunkEnd);
+ }
+
+ protected IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature,
+ IStoreAccessor accessor, MoveableList<Object> list, int chunkStart, int chunkEnd)
+ {
+ IStoreChunkReader chunkReader = null;
+ int fromIndex = -1;
+ for (int j = chunkStart; j < chunkEnd; j++)
+ {
+ if (list.get(j) == InternalCDOList.UNINITIALIZED)
+ {
+ if (fromIndex == -1)
+ {
+ fromIndex = j;
+ }
+ }
+ else
+ {
+ if (fromIndex != -1)
+ {
+ if (chunkReader == null)
+ {
+ if (accessor == null)
+ {
+ accessor = StoreThreadLocal.getAccessor();
+ }
+
+ chunkReader = accessor.createChunkReader(revision, feature);
+ }
+
+ int toIndex = j;
+ if (fromIndex == toIndex - 1)
+ {
+ chunkReader.addSimpleChunk(fromIndex);
+ }
+ else
+ {
+ chunkReader.addRangedChunk(fromIndex, toIndex);
+ }
+
+ fromIndex = -1;
+ }
+ }
+ }
+
+ // Add last chunk
+ if (fromIndex != -1)
+ {
+ if (chunkReader == null)
+ {
+ if (accessor == null)
+ {
+ accessor = StoreThreadLocal.getAccessor();
+ }
+
+ chunkReader = accessor.createChunkReader(revision, feature);
+ }
+
+ int toIndex = chunkEnd;
+ if (fromIndex == toIndex - 1)
+ {
+ chunkReader.addSimpleChunk(fromIndex);
+ }
+ else
+ {
+ chunkReader.addRangedChunk(fromIndex, toIndex);
+ }
+ }
+
+ if (chunkReader != null)
+ {
+ InternalCDOList cdoList = list instanceof InternalCDOList ? (InternalCDOList)list : null;
+
+ List<Chunk> chunks = chunkReader.executeRead();
+ for (Chunk chunk : chunks)
+ {
+ int startIndex = chunk.getStartIndex();
+ for (int indexInChunk = 0; indexInChunk < chunk.size(); indexInChunk++)
+ {
+ Object id = chunk.get(indexInChunk);
+ if (cdoList != null)
+ {
+ cdoList.setWithoutFrozenCheck(startIndex + indexInChunk, id);
+ }
+ else
+ {
+ list.set(startIndex + indexInChunk, id);
+ }
+ }
+ }
+ }
+
+ return accessor;
+ }
+
+ public InternalCDOPackageRegistry getPackageRegistry(boolean considerCommitContext)
+ {
+ if (considerCommitContext)
+ {
+ IStoreAccessor.CommitContext commitContext = StoreThreadLocal.getCommitContext();
+ if (commitContext != null)
+ {
+ InternalCDOPackageRegistry contextualPackageRegistry = commitContext.getPackageRegistry();
+ if (contextualPackageRegistry != null)
+ {
+ return contextualPackageRegistry;
+ }
+ }
+ }
+
+ return packageRegistry;
+ }
+
+ public Semaphore getPackageRegistryCommitLock()
+ {
+ return packageRegistryCommitLock;
+ }
+
+ public InternalCDOPackageRegistry getPackageRegistry()
+ {
+ return getPackageRegistry(true);
+ }
+
+ public void setPackageRegistry(InternalCDOPackageRegistry packageRegistry)
+ {
+ checkInactive();
+ this.packageRegistry = packageRegistry;
+ }
+
+ public InternalSessionManager getSessionManager()
+ {
+ return sessionManager;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void setSessionManager(InternalSessionManager sessionManager)
+ {
+ checkInactive();
+ this.sessionManager = sessionManager;
+ }
+
+ public InternalCDOBranchManager getBranchManager()
+ {
+ return branchManager;
+ }
+
+ public void setBranchManager(InternalCDOBranchManager branchManager)
+ {
+ checkInactive();
+ this.branchManager = branchManager;
+ }
+
+ public InternalCDOCommitInfoManager getCommitInfoManager()
+ {
+ return commitInfoManager;
+ }
+
+ public void setCommitInfoManager(InternalCDOCommitInfoManager commitInfoManager)
+ {
+ checkInactive();
+ this.commitInfoManager = commitInfoManager;
+ }
+
+ public InternalCDORevisionManager getRevisionManager()
+ {
+ return revisionManager;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void setRevisionManager(InternalCDORevisionManager revisionManager)
+ {
+ checkInactive();
+ this.revisionManager = revisionManager;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public InternalQueryManager getQueryManager()
+ {
+ return queryManager;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void setQueryManager(InternalQueryManager queryManager)
+ {
+ checkInactive();
+ this.queryManager = queryManager;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public InternalCommitManager getCommitManager()
+ {
+ return commitManager;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void setCommitManager(InternalCommitManager commitManager)
+ {
+ checkInactive();
+ this.commitManager = commitManager;
+ }
+
+ /**
+ * @since 2.0
+ * @deprecated
+ */
+ @Deprecated
+ public InternalLockManager getLockManager()
+ {
+ return getLockingManager();
+ }
+
+ public InternalLockManager getLockingManager()
+ {
+ return lockingManager;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void setLockingManager(InternalLockManager lockingManager)
+ {
+ checkInactive();
+ this.lockingManager = lockingManager;
+ }
+
+ public InternalCommitContext createCommitContext(InternalTransaction transaction)
+ {
+ return new TransactionCommitContext(transaction);
+ }
+
+ public long getLastCommitTimeStamp()
+ {
+ return timeStampAuthority.getLastFinishedTimeStamp();
+ }
+
+ public void setLastCommitTimeStamp(long lastCommitTimeStamp)
+ {
+ timeStampAuthority.setLastFinishedTimeStamp(lastCommitTimeStamp);
+ }
+
+ public long waitForCommit(long timeout)
+ {
+ return timeStampAuthority.waitForCommit(timeout);
+ }
+
+ public long[] createCommitTimeStamp(OMMonitor monitor)
+ {
+ return timeStampAuthority.startCommit(CDOBranchPoint.UNSPECIFIED_DATE, monitor);
+ }
+
+ public long[] forceCommitTimeStamp(long override, OMMonitor monitor)
+ {
+ return timeStampAuthority.startCommit(override, monitor);
+ }
+
+ public void endCommit(long timestamp)
+ {
+ timeStampAuthority.endCommit(timestamp);
+ }
+
+ public void failCommit(long timestamp)
+ {
+ timeStampAuthority.failCommit(timestamp);
+ }
+
+ public CDOCommitInfoHandler[] getCommitInfoHandlers()
+ {
+ synchronized (commitInfoHandlers)
+ {
+ return commitInfoHandlers.toArray(new CDOCommitInfoHandler[commitInfoHandlers.size()]);
+ }
+ }
+
+ /**
+ * @since 4.0
+ */
+ public void addCommitInfoHandler(CDOCommitInfoHandler handler)
+ {
+ synchronized (commitInfoHandlers)
+ {
+ if (!commitInfoHandlers.contains(handler))
+ {
+ commitInfoHandlers.add(handler);
+ }
+ }
+ }
+
+ /**
+ * @since 4.0
+ */
+ public void removeCommitInfoHandler(CDOCommitInfoHandler handler)
+ {
+ synchronized (commitInfoHandlers)
+ {
+ commitInfoHandlers.remove(handler);
+ }
+ }
+
+ public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo)
+ {
+ sessionManager.sendCommitNotification(sender, commitInfo);
+
+ for (CDOCommitInfoHandler handler : getCommitInfoHandlers())
+ {
+ try
+ {
+ handler.handleCommitInfo(commitInfo);
+ }
+ catch (Exception ex)
+ {
+ OM.LOG.error(ex);
+ }
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public IQueryHandlerProvider getQueryHandlerProvider()
+ {
+ return queryHandlerProvider;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void setQueryHandlerProvider(IQueryHandlerProvider queryHandlerProvider)
+ {
+ this.queryHandlerProvider = queryHandlerProvider;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public synchronized IQueryHandler getQueryHandler(CDOQueryInfo info)
+ {
+ String language = info.getQueryLanguage();
+ if (CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES.equals(language))
+ {
+ return new ResourcesQueryHandler();
+ }
+
+ if (CDOProtocolConstants.QUERY_LANGUAGE_XREFS.equals(language))
+ {
+ return new XRefsQueryHandler();
+ }
+
+ IStoreAccessor storeAccessor = StoreThreadLocal.getAccessor();
+ if (storeAccessor != null)
+ {
+ IQueryHandler handler = storeAccessor.getQueryHandler(info);
+ if (handler != null)
+ {
+ return handler;
+ }
+ }
+
+ if (queryHandlerProvider == null)
+ {
+ queryHandlerProvider = new ContainerQueryHandlerProvider(IPluginContainer.INSTANCE);
+ }
+
+ IQueryHandler handler = queryHandlerProvider.getQueryHandler(info);
+ if (handler != null)
+ {
+ return handler;
+ }
+
+ return null;
+ }
+
+ public Object[] getElements()
+ {
+ final Object[] elements = { packageRegistry, branchManager, revisionManager, sessionManager, queryManager,
+ commitManager, commitInfoManager, getLockingManager(), store };
+ return elements;
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return false;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public long getCreationTime()
+ {
+ return store.getCreationTime();
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void validateTimeStamp(long timeStamp) throws IllegalArgumentException
+ {
+ long creationTimeStamp = getCreationTime();
+ if (timeStamp < creationTimeStamp)
+ {
+ throw new IllegalArgumentException(
+ MessageFormat
+ .format(
+ "timeStamp ({0}) < repository creation time ({1})", CDOCommonUtil.formatTimeStamp(timeStamp), CDOCommonUtil.formatTimeStamp(creationTimeStamp))); //$NON-NLS-1$
+ }
+
+ long currentTimeStamp = getTimeStamp();
+ if (timeStamp > currentTimeStamp)
+ {
+ throw new IllegalArgumentException(
+ MessageFormat
+ .format(
+ "timeStamp ({0}) > current time ({1})", CDOCommonUtil.formatTimeStamp(timeStamp), CDOCommonUtil.formatTimeStamp(currentTimeStamp))); //$NON-NLS-1$
+ }
+ }
+
+ public long getTimeStamp()
+ {
+ return System.currentTimeMillis();
+ }
+
+ public Set<Handler> getHandlers()
+ {
+ Set<Handler> handlers = new HashSet<Handler>();
+
+ synchronized (readAccessHandlers)
+ {
+ handlers.addAll(readAccessHandlers);
+ }
+
+ synchronized (writeAccessHandlers)
+ {
+ handlers.addAll(writeAccessHandlers);
+ }
+
+ return handlers;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void addHandler(Handler handler)
+ {
+ if (handler instanceof ReadAccessHandler)
+ {
+ synchronized (readAccessHandlers)
+ {
+ if (!readAccessHandlers.contains(handler))
+ {
+ readAccessHandlers.add((ReadAccessHandler)handler);
+ }
+ }
+ }
+
+ if (handler instanceof WriteAccessHandler)
+ {
+ synchronized (writeAccessHandlers)
+ {
+ if (!writeAccessHandlers.contains(handler))
+ {
+ writeAccessHandlers.add((WriteAccessHandler)handler);
+ }
+ }
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void removeHandler(Handler handler)
+ {
+ if (handler instanceof ReadAccessHandler)
+ {
+ synchronized (readAccessHandlers)
+ {
+ readAccessHandlers.remove(handler);
+ }
+ }
+
+ if (handler instanceof WriteAccessHandler)
+ {
+ synchronized (writeAccessHandlers)
+ {
+ writeAccessHandlers.remove(handler);
+ }
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void notifyReadAccessHandlers(InternalSession session, CDORevision[] revisions,
+ List<CDORevision> additionalRevisions)
+ {
+ ReadAccessHandler[] handlers;
+ synchronized (readAccessHandlers)
+ {
+ int size = readAccessHandlers.size();
+ if (size == 0)
+ {
+ return;
+ }
+
+ handlers = readAccessHandlers.toArray(new ReadAccessHandler[size]);
+ }
+
+ for (ReadAccessHandler handler : handlers)
+ {
+ // Do *not* protect against unchecked exceptions from handlers!
+ handler.handleRevisionsBeforeSending(session, revisions, additionalRevisions);
+ }
+ }
+
+ public void notifyWriteAccessHandlers(ITransaction transaction, IStoreAccessor.CommitContext commitContext,
+ boolean beforeCommit, OMMonitor monitor)
+ {
+ WriteAccessHandler[] handlers;
+ synchronized (writeAccessHandlers)
+ {
+ int size = writeAccessHandlers.size();
+ if (size == 0)
+ {
+ return;
+ }
+
+ handlers = writeAccessHandlers.toArray(new WriteAccessHandler[size]);
+ }
+
+ try
+ {
+ monitor.begin(handlers.length);
+ for (WriteAccessHandler handler : handlers)
+ {
+ try
+ {
+ if (beforeCommit)
+ {
+ handler.handleTransactionBeforeCommitting(transaction, commitContext, monitor.fork());
+ }
+ else
+ {
+ handler.handleTransactionAfterCommitted(transaction, commitContext, monitor.fork());
+ }
+ }
+ catch (RuntimeException ex)
+ {
+ if (!beforeCommit)
+ {
+ OM.LOG.error(ex);
+ }
+ else
+ {
+ // Do *not* protect against unchecked exceptions from handlers on before case!
+ throw ex;
+ }
+ }
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ public void setInitialPackages(EPackage... initialPackages)
+ {
+ checkInactive();
+ this.initialPackages = initialPackages;
+ }
+
+ public CDOReplicationInfo replicateRaw(CDODataOutput out, int lastReplicatedBranchID, long lastReplicatedCommitTime)
+ throws IOException
+ {
+ final int fromBranchID = lastReplicatedBranchID + 1;
+ final int toBranchID = getStore().getLastBranchID();
+
+ final long fromCommitTime = lastReplicatedCommitTime + 1L;
+ final long toCommitTime = getStore().getLastCommitTime();
+
+ out.writeInt(toBranchID);
+ out.writeLong(toCommitTime);
+
+ IStoreAccessor.Raw accessor = (IStoreAccessor.Raw)StoreThreadLocal.getAccessor();
+ accessor.rawExport(out, fromBranchID, toBranchID, fromCommitTime, toCommitTime);
+
+ return new CDOReplicationInfo()
+ {
+ public int getLastReplicatedBranchID()
+ {
+ return toBranchID;
+ }
+
+ public long getLastReplicatedCommitTime()
+ {
+ return toCommitTime;
+ }
+
+ public String[] getLockAreaIDs()
+ {
+ return null; // TODO (CD) Raw replication of lockAreas
+ }
+ };
+ }
+
+ public void replicate(CDOReplicationContext context)
+ {
+ int startID = context.getLastReplicatedBranchID() + 1;
+ branchManager.getBranches(startID, 0, context);
+
+ long startTime = context.getLastReplicatedCommitTime();
+ commitInfoManager.getCommitInfos(null, startTime + 1L, CDOBranchPoint.UNSPECIFIED_DATE, context);
+
+ getLockingManager().getLockAreas(null, context);
+ }
+
+ public CDOChangeSetData getChangeSet(CDOBranchPoint startPoint, CDOBranchPoint endPoint)
+ {
+ CDOChangeSetSegment[] segments = CDOChangeSetSegment.createFrom(startPoint, endPoint);
+
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ Set<CDOID> ids = accessor.readChangeSet(new Monitor(), segments);
+
+ return CDORevisionUtil.createChangeSetData(ids, startPoint, endPoint, revisionManager);
+ }
+
+ public Set<CDOID> getMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo,
+ CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor)
+ {
+ CDOBranchPoint target = targetInfo.getBranchPoint();
+ CDOBranchPoint source = sourceInfo.getBranchPoint();
+
+ monitor.begin(5);
+
+ try
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ Set<CDOID> ids = new HashSet<CDOID>();
+
+ if (targetBaseInfo == null && sourceBaseInfo == null)
+ {
+ if (CDOBranchUtil.isContainedBy(source, target))
+ {
+ ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(source, target)));
+ }
+ else if (CDOBranchUtil.isContainedBy(target, source))
+ {
+ ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(target, source)));
+ }
+ else
+ {
+ CDOBranchPoint ancestor = CDOBranchUtil.getAncestor(target, source);
+ ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(ancestor, target)));
+ ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(ancestor, source)));
+ }
+ }
+ else
+ {
+ CDORevisionAvailabilityInfo sourceBaseInfoToUse = sourceBaseInfo == null ? targetBaseInfo : sourceBaseInfo;
+
+ ids.addAll(accessor.readChangeSet(monitor.fork(),
+ CDOChangeSetSegment.createFrom(targetBaseInfo.getBranchPoint(), target)));
+
+ ids.addAll(accessor.readChangeSet(monitor.fork(),
+ CDOChangeSetSegment.createFrom(sourceBaseInfoToUse.getBranchPoint(), source)));
+ }
+
+ loadMergeData(ids, targetInfo, monitor.fork());
+ loadMergeData(ids, sourceInfo, monitor.fork());
+
+ if (targetBaseInfo != null)
+ {
+ loadMergeData(ids, targetBaseInfo, monitor.fork());
+ }
+
+ if (sourceBaseInfo != null)
+ {
+ loadMergeData(ids, sourceBaseInfo, monitor.fork());
+ }
+
+ return ids;
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ private void loadMergeData(Set<CDOID> ids, CDORevisionAvailabilityInfo info, OMMonitor monitor)
+ {
+ int size = ids.size();
+ monitor.begin(size);
+
+ try
+ {
+ CDOBranchPoint branchPoint = info.getBranchPoint();
+ for (CDOID id : ids)
+ {
+ if (info.containsRevision(id))
+ {
+ info.removeRevision(id);
+ }
+ else
+ {
+ InternalCDORevision revision = getRevisionFromBranch(id, branchPoint);
+ if (revision != null)
+ {
+ info.addRevision(revision);
+ }
+ else
+ {
+ info.removeRevision(id);
+ }
+ }
+
+ monitor.worked();
+ }
+ }
+ finally
+ {
+ monitor.done();
+ }
+ }
+
+ private InternalCDORevision getRevisionFromBranch(CDOID id, CDOBranchPoint branchPoint)
+ {
+ InternalCDORevision revision = revisionManager.getRevision(id, branchPoint, CDORevision.UNCHUNKED,
+ CDORevision.DEPTH_NONE, true);
+ // if (revision == null || !ObjectUtil.equals(revision.getBranch(), branchPoint.getBranch()))
+ // {
+ // return null;
+ // }
+
+ return revision;
+ }
+
+ public void queryLobs(List<byte[]> ids)
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ accessor.queryLobs(ids);
+ }
+
+ public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ accessor.handleLobs(fromTime, toTime, handler);
+ }
+
+ public void loadLob(byte[] id, OutputStream out) throws IOException
+ {
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ accessor.loadLob(id, out);
+ }
+
+ public void handleRevisions(EClass eClass, CDOBranch branch, boolean exactBranch, long timeStamp, boolean exactTime,
+ final CDORevisionHandler handler)
+ {
+ CDORevisionHandler wrapper = handler;
+ if (!exactBranch && !branch.isMainBranch())
+ {
+ if (exactTime && timeStamp == CDOBranchPoint.UNSPECIFIED_DATE)
+ {
+ throw new IllegalArgumentException("Time stamp must be specified if exactBranch==false and exactTime==true");
+ }
+
+ wrapper = new CDORevisionHandler()
+ {
+ private Set<CDOID> handled = new HashSet<CDOID>();
+
+ public boolean handleRevision(CDORevision revision)
+ {
+ CDOID id = revision.getID();
+ if (handled.add(id))
+ {
+ return handler.handleRevision(revision);
+ }
+
+ return true;
+ }
+ };
+ }
+
+ IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+ while (branch != null)
+ {
+ accessor.handleRevisions(eClass, branch, timeStamp, exactTime, wrapper);
+ if (exactBranch)
+ {
+ break;
+ }
+
+ CDOBranchPoint base = branch.getBase();
+ branch = base.getBranch();
+ timeStamp = base.getTimeStamp();
+ }
+ }
+
+ public static List<Object> revisionKeysToObjects(List<CDORevisionKey> revisionKeys, CDOBranch viewedBranch,
+ boolean isSupportingBranches)
+ {
+ List<Object> lockables = new ArrayList<Object>();
+ for (CDORevisionKey revKey : revisionKeys)
+ {
+ CDOID id = revKey.getID();
+ if (isSupportingBranches)
+ {
+ lockables.add(CDOIDUtil.createIDAndBranch(id, viewedBranch));
+ }
+ else
+ {
+ lockables.add(id);
+ }
+ }
+ return lockables;
+ }
+
+ public LockObjectsResult lock(InternalView view, LockType lockType, List<CDORevisionKey> revKeys, boolean recursive,
+ long timeout)
+ {
+ List<Object> lockables = revisionKeysToObjects(revKeys, view.getBranch(), isSupportingBranches());
+ return lock(view, lockType, lockables, revKeys, recursive, timeout);
+ }
+
+ protected LockObjectsResult lock(InternalView view, LockType type, List<Object> lockables,
+ List<CDORevisionKey> loadedRevs, boolean recursive, long timeout)
+ {
+ List<LockState<Object, IView>> newLockStates = null;
+ try
+ {
+ newLockStates = getLockingManager().lock2(true, type, view, lockables, recursive, timeout);
+ }
+ catch (TimeoutRuntimeException ex)
+ {
+ return new LockObjectsResult(false, true, false, 0, new CDORevisionKey[0], new CDOLockState[0], getTimeStamp());
+ }
+ catch (InterruptedException ex)
+ {
+ throw WrappedException.wrap(ex);
+ }
+
+ long[] requiredTimestamp = { 0L };
+ CDORevisionKey[] staleRevisionsArray = null;
+
+ try
+ {
+ staleRevisionsArray = checkStaleRevisions(view, loadedRevs, lockables, type, requiredTimestamp);
+ }
+ catch (IllegalArgumentException e)
+ {
+ getLockingManager().unlock2(true, type, view, lockables, recursive);
+ throw e;
+ }
+
+ // If some of the clients' revisions are stale and it has passiveUpdates disabled,
+ // then the locks are useless so we release them and report the stale revisions
+ //
+ InternalSession session = view.getSession();
+ boolean staleNoUpdate = staleRevisionsArray.length > 0 && !session.isPassiveUpdateEnabled();
+ if (staleNoUpdate)
+ {
+ getLockingManager().unlock2(true, type, view, lockables, recursive);
+ return new LockObjectsResult(false, false, false, requiredTimestamp[0], staleRevisionsArray, new CDOLockState[0],
+ getTimeStamp());
+ }
+
+ CDOLockState[] cdoLockStates = toCDOLockStates(newLockStates);
+ sendLockNotifications(view, Operation.LOCK, type, cdoLockStates);
+
+ boolean waitForUpdate = staleRevisionsArray.length > 0;
+ return new LockObjectsResult(true, false, waitForUpdate, requiredTimestamp[0], staleRevisionsArray, cdoLockStates,
+ getTimeStamp());
+ }
+
+ private CDORevisionKey[] checkStaleRevisions(InternalView view, List<CDORevisionKey> revisionKeys,
+ List<Object> objectsToLock, LockType lockType, long[] requiredTimestamp)
+ {
+ List<CDORevisionKey> staleRevisions = new LinkedList<CDORevisionKey>();
+ if (revisionKeys != null)
+ {
+ InternalCDORevisionManager revManager = getRevisionManager();
+ CDOBranch viewedBranch = view.getBranch();
+ for (CDORevisionKey revKey : revisionKeys)
+ {
+ CDOID id = revKey.getID();
+ InternalCDORevision rev = revManager.getRevision(id, viewedBranch.getHead(), CDORevision.UNCHUNKED,
+ CDORevision.DEPTH_NONE, true);
+
+ if (rev == null)
+ {
+ throw new IllegalArgumentException(String.format("Object %s not found in branch %s (possibly detached)", id,
+ viewedBranch));
+ }
+
+ if (!revKey.equals(rev))
+ {
+ staleRevisions.add(revKey);
+ requiredTimestamp[0] = Math.max(requiredTimestamp[0], rev.getTimeStamp());
+ }
+ }
+ }
+
+ // Convert the list to an array, to satisfy the API later
+ //
+ CDORevisionKey[] staleRevisionsArray = new CDORevisionKey[staleRevisions.size()];
+ staleRevisions.toArray(staleRevisionsArray);
+
+ return staleRevisionsArray;
+ }
+
+ private void sendLockNotifications(IView view, Operation operation, LockType lockType, CDOLockState[] cdoLockStates)
+ {
+ long timestamp = getTimeStamp();
+ CDOLockChangeInfo lockChangeInfo = CDOLockUtil.createLockChangeInfo(timestamp, view, view.getBranch(), operation,
+ lockType, cdoLockStates);
+ getSessionManager().sendLockNotification((InternalSession)view.getSession(), lockChangeInfo);
+ }
+
+ // TODO (CD) This doesn't really belong here.. but getting it into CDOLockUtil isn't possible
+ public static CDOLockState[] toCDOLockStates(List<LockState<Object, IView>> lockStates)
+ {
+ CDOLockState[] cdoLockStates = new CDOLockState[lockStates.size()];
+ int i = 0;
+
+ for (LockState<Object, ? extends CDOCommonView> lockState : lockStates)
+ {
+ CDOLockState cdoLockState = CDOLockUtil.createLockState(lockState);
+ cdoLockStates[i++] = cdoLockState;
+ }
+
+ return cdoLockStates;
+ }
+
+ public UnlockObjectsResult unlock(InternalView view, LockType lockType, List<CDOID> objectIDs, boolean recursive)
+ {
+ List<Object> unlockables = null;
+ if (objectIDs != null)
+ {
+ unlockables = new ArrayList<Object>(objectIDs.size());
+ CDOBranch branch = view.getBranch();
+ for (CDOID id : objectIDs)
+ {
+ Object key = supportingBranches ? CDOIDUtil.createIDAndBranch(id, branch) : id;
+ unlockables.add(key);
+ }
+ }
+
+ return doUnlock(view, lockType, unlockables, recursive);
+ }
+
+ protected UnlockObjectsResult doUnlock(InternalView view, LockType lockType, List<Object> unlockables,
+ boolean recursive)
+ {
+ List<LockState<Object, IView>> newLockStates = null;
+ if (lockType == null) // Signals an unlock-all operation
+ {
+ newLockStates = getLockingManager().unlock2(true, view);
+ }
+ else
+ {
+ newLockStates = getLockingManager().unlock2(true, lockType, view, unlockables, recursive);
+ }
+
+ long timestamp = getTimeStamp();
+ CDOLockState[] cdoLockStates = toCDOLockStates(newLockStates);
+ sendLockNotifications(view, Operation.UNLOCK, lockType, cdoLockStates);
+
+ return new UnlockObjectsResult(cdoLockStates, timestamp);
+ }
+
+ @Override
+ public String toString()
+ {
+ return MessageFormat.format("Repository[{0}]", name); //$NON-NLS-1$
+ }
+
+ public boolean isSkipInitialization()
+ {
+ return skipInitialization;
+ }
+
+ public void setSkipInitialization(boolean skipInitialization)
+ {
+ this.skipInitialization = skipInitialization;
+ }
+
+ protected void initProperties()
+ {
+ String valueAudits = properties.get(Props.SUPPORTING_AUDITS);
+ if (valueAudits != null)
+ {
+ supportingAudits = Boolean.valueOf(valueAudits);
+ }
+ else
+ {
+ supportingAudits = store.getRevisionTemporality() == IStore.RevisionTemporality.AUDITING;
+ }
+
+ String valueBranches = properties.get(Props.SUPPORTING_BRANCHES);
+ if (valueBranches != null)
+ {
+ supportingBranches = Boolean.valueOf(valueBranches);
+ }
+ else
+ {
+ supportingBranches = store.getRevisionParallelism() == IStore.RevisionParallelism.BRANCHING;
+ }
+
+ String valueEcore = properties.get(Props.SUPPORTING_ECORE);
+ if (valueEcore != null)
+ {
+ supportingEcore = Boolean.valueOf(valueEcore);
+ }
+
+ String valueIntegrity = properties.get(Props.ENSURE_REFERENTIAL_INTEGRITY);
+ if (valueIntegrity != null)
+ {
+ ensuringReferentialIntegrity = Boolean.valueOf(valueIntegrity);
+ }
+
+ String valueIDLocation = properties.get(Props.ID_GENERATION_LOCATION);
+ if (valueIDLocation != null)
+ {
+ idGenerationLocation = IDGenerationLocation.valueOf(valueIDLocation);
+ }
+
+ if (idGenerationLocation == null)
+ {
+ idGenerationLocation = IDGenerationLocation.STORE;
+ }
+ }
+
+ public void initSystemPackages()
+ {
+ IStoreAccessor writer = store.getWriter(null);
+ StoreThreadLocal.setAccessor(writer);
+
+ try
+ {
+ List<InternalCDOPackageUnit> units = new ArrayList<InternalCDOPackageUnit>();
+ units.add(initSystemPackage(EcorePackage.eINSTANCE));
+ units.add(initSystemPackage(EresourcePackage.eINSTANCE));
+ units.add(initSystemPackage(EtypesPackage.eINSTANCE));
+
+ if (initialPackages != null)
+ {
+ for (EPackage initialPackage : initialPackages)
+ {
+ if (!packageRegistry.containsKey(initialPackage.getNsURI()))
+ {
+ units.add(initSystemPackage(initialPackage));
+ }
+ }
+ }
+
+ InternalCDOPackageUnit[] systemUnits = units.toArray(new InternalCDOPackageUnit[units.size()]);
+ writer.writePackageUnits(systemUnits, new Monitor());
+ writer.commit(new Monitor());
+ }
+ finally
+ {
+ StoreThreadLocal.release();
+ }
+ }
+
+ protected InternalCDOPackageUnit initSystemPackage(EPackage ePackage)
+ {
+ EMFUtil.registerPackage(ePackage, packageRegistry);
+ InternalCDOPackageInfo packageInfo = packageRegistry.getPackageInfo(ePackage);
+
+ InternalCDOPackageUnit packageUnit = packageInfo.getPackageUnit();
+ packageUnit.setTimeStamp(store.getCreationTime());
+ packageUnit.setState(CDOPackageUnit.State.LOADED);
+ return packageUnit;
+ }
+
+ public void initMainBranch(InternalCDOBranchManager branchManager, long timeStamp)
+ {
+ branchManager.initMainBranch(false, timeStamp);
+ }
+
+ protected void initRootResource()
+ {
+ CDOBranchPoint head = branchManager.getMainBranch().getHead();
+
+ CDORevisionFactory factory = getRevisionManager().getFactory();
+ InternalCDORevision rootResource = (InternalCDORevision)factory
+ .createRevision(EresourcePackage.Literals.CDO_RESOURCE);
+
+ rootResource.setBranchPoint(head);
+ rootResource.setContainerID(CDOID.NULL);
+ rootResource.setContainingFeatureID(0);
+
+ CDOID id = createRootResourceID();
+ rootResource.setID(id);
+ rootResource.setResourceID(id);
+
+ InternalSession session = getSessionManager().openSession(null);
+ InternalTransaction transaction = session.openTransaction(1, head);
+ InternalCommitContext commitContext = new TransactionCommitContext(transaction)
+ {
+ @Override
+ protected long[] createTimeStamp(OMMonitor monitor)
+ {
+ InternalRepository repository = getTransaction().getSession().getManager().getRepository();
+ return repository.forceCommitTimeStamp(store.getCreationTime(), monitor);
+ }
+
+ @Override
+ public String getUserID()
+ {
+ return SYSTEM_USER_ID;
+ }
+
+ @Override
+ public String getCommitComment()
+ {
+ return "<initialize>"; //$NON-NLS-1$
+ }
+ };
+
+ commitContext.setNewObjects(new InternalCDORevision[] { rootResource });
+ commitContext.preWrite();
+
+ commitContext.write(new Monitor());
+ commitContext.commit(new Monitor());
+
+ String rollbackMessage = commitContext.getRollbackMessage();
+ if (rollbackMessage != null)
+ {
+ throw new TransactionException(rollbackMessage);
+ }
+
+ rootResourceID = id instanceof CDOIDTemp ? commitContext.getIDMappings().get(id) : id;
+
+ commitContext.postCommit(true);
+ session.close();
+ }
+
+ protected CDOID createRootResourceID()
+ {
+ if (getIDGenerationLocation() == IDGenerationLocation.STORE)
+ {
+ return CDOIDUtil.createTempObject(1);
+ }
+
+ return CDOIDGenerator.UUID.generateCDOID(null);
+ }
+
+ protected void readRootResource()
+ {
+ IStoreAccessor reader = store.getReader(null);
+ StoreThreadLocal.setAccessor(reader);
+
+ try
+ {
+ CDOBranchPoint head = branchManager.getMainBranch().getHead();
+ rootResourceID = reader.readResourceID(CDOID.NULL, null, head);
+ }
+ finally
+ {
+ StoreThreadLocal.release();
+ }
+ }
+
+ protected void readPackageUnits()
+ {
+ IStoreAccessor reader = store.getReader(null);
+ StoreThreadLocal.setAccessor(reader);
+
+ try
+ {
+ Collection<InternalCDOPackageUnit> packageUnits = reader.readPackageUnits();
+ for (InternalCDOPackageUnit packageUnit : packageUnits)
+ {
+ packageRegistry.putPackageUnit(packageUnit);
+ }
+ }
+ finally
+ {
+ StoreThreadLocal.release();
+ }
+ }
+
+ @Override
+ protected void doBeforeActivate() throws Exception
+ {
+ super.doBeforeActivate();
+ checkState(store, "store"); //$NON-NLS-1$
+ checkState(!StringUtil.isEmpty(name), "name is empty"); //$NON-NLS-1$
+ checkState(packageRegistry, "packageRegistry"); //$NON-NLS-1$
+ checkState(sessionManager, "sessionManager"); //$NON-NLS-1$
+ checkState(branchManager, "branchManager"); //$NON-NLS-1$
+ checkState(revisionManager, "revisionManager"); //$NON-NLS-1$
+ checkState(queryManager, "queryManager"); //$NON-NLS-1$
+ checkState(commitInfoManager, "commitInfoManager"); //$NON-NLS-1$
+ checkState(commitManager, "commitManager"); //$NON-NLS-1$
+ checkState(getLockingManager(), "lockingManager"); //$NON-NLS-1$
+
+ packageRegistry.setReplacingDescriptors(true);
+ packageRegistry.setPackageProcessor(this);
+ packageRegistry.setPackageLoader(this);
+
+ branchManager.setBranchLoader(this);
+ branchManager.setTimeProvider(this);
+
+ revisionManager.setRevisionLoader(this);
+ sessionManager.setRepository(this);
+ queryManager.setRepository(this);
+ commitInfoManager.setCommitInfoLoader(this);
+ commitManager.setRepository(this);
+ getLockingManager().setRepository(this);
+ store.setRepository(this);
+ }
+
+ @Override
+ protected void doActivate() throws Exception
+ {
+ super.doActivate();
+
+ initProperties();
+ if (idGenerationLocation == IDGenerationLocation.CLIENT && !(store instanceof CanHandleClientAssignedIDs))
+ {
+ throw new IllegalStateException("Store can not handle client assigned IDs: " + store);
+ }
+
+ store.setRevisionTemporality(supportingAudits ? IStore.RevisionTemporality.AUDITING
+ : IStore.RevisionTemporality.NONE);
+ store.setRevisionParallelism(supportingBranches ? IStore.RevisionParallelism.BRANCHING
+ : IStore.RevisionParallelism.NONE);
+ revisionManager.setSupportingAudits(supportingAudits);
+ revisionManager.setSupportingBranches(supportingBranches);
+
+ LifecycleUtil.activate(store);
+ LifecycleUtil.activate(packageRegistry);
+ LifecycleUtil.activate(sessionManager);
+ LifecycleUtil.activate(revisionManager);
+ LifecycleUtil.activate(branchManager);
+ LifecycleUtil.activate(queryManager);
+ LifecycleUtil.activate(commitInfoManager);
+ LifecycleUtil.activate(commitManager);
+ LifecycleUtil.activate(queryHandlerProvider);
+
+ if (!skipInitialization)
+ {
+ long lastCommitTimeStamp = Math.max(store.getCreationTime(), store.getLastCommitTime());
+ timeStampAuthority.setLastFinishedTimeStamp(lastCommitTimeStamp);
+ initMainBranch(branchManager, lastCommitTimeStamp);
+
+ if (store.isFirstStart())
+ {
+ initSystemPackages();
+ initRootResource();
+ }
+ else
+ {
+ readPackageUnits();
+ readRootResource();
+ }
+
+ // This check does not work for CDOWorkspace:
+ // if (CDOIDUtil.isNull(rootResourceID))
+ // {
+ // throw new IllegalStateException("Root resource ID is null");
+ // }
+ }
+
+ LifecycleUtil.activate(getLockingManager()); // Needs an initialized main branch / branch manager
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ LifecycleUtil.deactivate(getLockingManager());
+ LifecycleUtil.deactivate(queryHandlerProvider);
+ LifecycleUtil.deactivate(commitManager);
+ LifecycleUtil.deactivate(commitInfoManager);
+ LifecycleUtil.deactivate(queryManager);
+ LifecycleUtil.deactivate(revisionManager);
+ LifecycleUtil.deactivate(sessionManager);
+ LifecycleUtil.deactivate(store);
+ LifecycleUtil.deactivate(branchManager);
+ LifecycleUtil.deactivate(packageRegistry);
+ super.doDeactivate();
+ }
+
+ /**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+ public static class Default extends Repository
+ {
+ public Default()
+ {
+ }
+
+ @Override
+ protected void doBeforeActivate() throws Exception
+ {
+ if (getPackageRegistry(false) == null)
+ {
+ setPackageRegistry(createPackageRegistry());
+ }
+
+ if (getSessionManager() == null)
+ {
+ setSessionManager(createSessionManager());
+ }
+
+ if (getBranchManager() == null)
+ {
+ setBranchManager(createBranchManager());
+ }
+
+ if (getRevisionManager() == null)
+ {
+ setRevisionManager(createRevisionManager());
+ }
+
+ if (getQueryManager() == null)
+ {
+ setQueryManager(createQueryManager());
+ }
+
+ if (getCommitInfoManager() == null)
+ {
+ setCommitInfoManager(createCommitInfoManager());
+ }
+
+ if (getCommitManager() == null)
+ {
+ setCommitManager(createCommitManager());
+ }
+
+ if (getLockManager() == null)
+ {
+ setLockingManager(createLockManager());
+ }
+
+ super.doBeforeActivate();
+ }
+
+ protected InternalCDOPackageRegistry createPackageRegistry()
+ {
+ return new CDOPackageRegistryImpl();
+ }
+
+ protected InternalSessionManager createSessionManager()
+ {
+ return new SessionManager();
+ }
+
+ protected InternalCDOBranchManager createBranchManager()
+ {
+ return CDOBranchUtil.createBranchManager();
+ }
+
+ protected InternalCDORevisionManager createRevisionManager()
+ {
+ return (InternalCDORevisionManager)CDORevisionUtil.createRevisionManager();
+ }
+
+ protected InternalQueryManager createQueryManager()
+ {
+ return new QueryManager();
+ }
+
+ protected InternalCDOCommitInfoManager createCommitInfoManager()
+ {
+ return CDOCommitInfoUtil.createCommitInfoManager();
+ }
+
+ protected InternalCommitManager createCommitManager()
+ {
+ return new CommitManager();
+ }
+
+ @Deprecated
+ protected InternalLockManager createLockManager()
+ {
+ return createLockingManager();
+ }
+
+ public LockingManager createLockingManager()
+ {
+ return new LockingManager();
+ }
+ }
+}
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 a7c41b81e6..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 @@ -26,6 +26,7 @@ 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; @@ -1037,7 +1038,13 @@ public class TransactionCommitContext implements InternalCommitContext } // Make sure all chunks are loaded - repository.ensureChunks(oldRevision); + 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); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java index 07bf2e1403..55ad08cb15 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java @@ -1,301 +1,319 @@ -/* - * 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 233490 - */ -package org.eclipse.emf.cdo.internal.server; - -import org.eclipse.emf.cdo.common.CDOCommonView; -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.revision.CDORevision; -import org.eclipse.emf.cdo.common.revision.CDORevisionManager; -import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; -import org.eclipse.emf.cdo.spi.server.InternalRepository; -import org.eclipse.emf.cdo.spi.server.InternalSession; -import org.eclipse.emf.cdo.spi.server.InternalView; - -import org.eclipse.net4j.util.ObjectUtil; -import org.eclipse.net4j.util.lifecycle.Lifecycle; -import org.eclipse.net4j.util.options.IOptionsContainer; - -import java.text.MessageFormat; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -/** - * @author Eike Stepper - */ -public class View extends Lifecycle implements InternalView, CDOCommonView.Options -{ - private InternalSession session; - - private final int viewID; - - private final int sessionID; // Needed here so we can compute the hashCode even after session becomes null due to - // deactivation! - - private CDOBranchPoint branchPoint; - - private String durableLockingID; - - private InternalRepository repository; - - private Set<CDOID> changeSubscriptionIDs = new HashSet<CDOID>(); - - private boolean lockNotificationsEnabled; - - /** - * @since 2.0 - */ - public View(InternalSession session, int viewID, CDOBranchPoint branchPoint) - { - this.session = session; - this.viewID = viewID; - sessionID = session.getSessionID(); - - repository = session.getManager().getRepository(); - setBranchPoint(branchPoint); - } - - public InternalSession getSession() - { - return session; - } - - public int getSessionID() - { - return session.getSessionID(); - } - - public int getViewID() - { - return viewID; - } - - public CDOBranch getBranch() - { - return branchPoint.getBranch(); - } - - public long getTimeStamp() - { - return branchPoint.getTimeStamp(); - } - - public boolean isReadOnly() - { - return true; - } - - public boolean isDurableView() - { - return durableLockingID != null; - } - - public String getDurableLockingID() - { - return durableLockingID; - } - - /** - * @since 2.0 - */ - public InternalRepository getRepository() - { - checkOpen(); - return repository; - } - - public InternalCDORevision getRevision(CDOID id) - { - CDORevisionManager revisionManager = repository.getRevisionManager(); - return (InternalCDORevision)revisionManager.getRevision(id, this, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, - true); - } - - public void changeTarget(CDOBranchPoint branchPoint, List<CDOID> invalidObjects, - List<CDORevisionDelta> allChangedObjects, List<CDOID> allDetachedObjects) - { - List<CDORevision> oldRevisions = getRevisions(invalidObjects); - setBranchPoint(branchPoint); - List<CDORevision> newRevisions = getRevisions(invalidObjects); - - Iterator<CDORevision> it = newRevisions.iterator(); - for (CDORevision oldRevision : oldRevisions) - { - CDORevision newRevision = it.next(); - if (newRevision == null) - { - allDetachedObjects.add(oldRevision.getID()); - } - else if (newRevision != oldRevision) - { - // Fix for Bugzilla 369646: ensure that revisions are fully loaded - repository.ensureChunks((InternalCDORevision)newRevision); - repository.ensureChunks((InternalCDORevision)oldRevision); - - CDORevisionDelta delta = newRevision.compare(oldRevision); - allChangedObjects.add(delta); - } - } - } - - private List<CDORevision> getRevisions(List<CDOID> ids) - { - return repository.getRevisionManager().getRevisions(ids, branchPoint, CDORevision.UNCHUNKED, - CDORevision.DEPTH_NONE, true); - } - - public void setBranchPoint(CDOBranchPoint branchPoint) - { - checkOpen(); - long timeStamp = branchPoint.getTimeStamp(); - branchPoint = branchPoint.getBranch().getPoint(timeStamp); - validateTimeStamp(timeStamp); - this.branchPoint = branchPoint; - } - - protected void validateTimeStamp(long timeStamp) throws IllegalArgumentException - { - if (timeStamp != UNSPECIFIED_DATE) - { - repository.validateTimeStamp(timeStamp); - } - } - - public void setDurableLockingID(String durableLockingID) - { - this.durableLockingID = durableLockingID; - } - - /** - * @since 2.0 - */ - public synchronized void subscribe(CDOID id) - { - checkOpen(); - changeSubscriptionIDs.add(id); - } - - /** - * @since 2.0 - */ - public synchronized void unsubscribe(CDOID id) - { - checkOpen(); - changeSubscriptionIDs.remove(id); - } - - /** - * @since 2.0 - */ - public synchronized boolean hasSubscription(CDOID id) - { - checkOpen(); - return changeSubscriptionIDs.contains(id); - } - - /** - * @since 2.0 - */ - public synchronized void clearChangeSubscription() - { - checkOpen(); - changeSubscriptionIDs.clear(); - } - - @Override - public int hashCode() - { - return ObjectUtil.hashCode(sessionID, viewID); - } - - @Override - public String toString() - { - int sessionID = session == null ? 0 : session.getSessionID(); - return MessageFormat.format("{0}[{1}:{2}]", getClassName(), sessionID, viewID); //$NON-NLS-1$ - } - - protected String getClassName() - { - return "View"; //$NON-NLS-1$ - } - - /** - * @since 2.0 - */ - public void close() - { - deactivate(); - } - - @Override - protected void doDeactivate() throws Exception - { - if (!isClosed()) - { - session.viewClosed(this); - } - - super.doDeactivate(); - } - - /** - * @since 2.0 - */ - public void doClose() - { - clearChangeSubscription(); - changeSubscriptionIDs = null; - session = null; - repository = null; - } - - /** - * @since 2.0 - */ - public boolean isClosed() - { - return repository == null; - } - - private void checkOpen() - { - if (isClosed()) - { - throw new IllegalStateException("View closed"); //$NON-NLS-1$ - } - } - - public IOptionsContainer getContainer() - { - return this; - } - - public Options options() - { - return this; - } - - public boolean isLockNotificationEnabled() - { - return lockNotificationsEnabled; - } - - public void setLockNotificationEnabled(boolean enable) - { - lockNotificationsEnabled = enable; - } -} +/*
+ * 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 233490
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonView;
+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.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.options.IOptionsContainer;
+
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.text.MessageFormat;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ */
+public class View extends Lifecycle implements InternalView, CDOCommonView.Options
+{
+ private InternalSession session;
+
+ private final int viewID;
+
+ private final int sessionID; // Needed here so we can compute the hashCode even after session becomes null due to
+ // deactivation!
+
+ private CDOBranchPoint branchPoint;
+
+ private String durableLockingID;
+
+ private InternalRepository repository;
+
+ private Set<CDOID> changeSubscriptionIDs = new HashSet<CDOID>();
+
+ private boolean lockNotificationsEnabled;
+
+ /**
+ * @since 2.0
+ */
+ public View(InternalSession session, int viewID, CDOBranchPoint branchPoint)
+ {
+ this.session = session;
+ this.viewID = viewID;
+ sessionID = session.getSessionID();
+
+ repository = session.getManager().getRepository();
+ setBranchPoint(branchPoint);
+ }
+
+ public InternalSession getSession()
+ {
+ return session;
+ }
+
+ public int getSessionID()
+ {
+ return session.getSessionID();
+ }
+
+ public int getViewID()
+ {
+ return viewID;
+ }
+
+ public CDOBranch getBranch()
+ {
+ return branchPoint.getBranch();
+ }
+
+ public long getTimeStamp()
+ {
+ return branchPoint.getTimeStamp();
+ }
+
+ public boolean isReadOnly()
+ {
+ return true;
+ }
+
+ public boolean isDurableView()
+ {
+ return durableLockingID != null;
+ }
+
+ public String getDurableLockingID()
+ {
+ return durableLockingID;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public InternalRepository getRepository()
+ {
+ checkOpen();
+ return repository;
+ }
+
+ public InternalCDORevision getRevision(CDOID id)
+ {
+ CDORevisionManager revisionManager = repository.getRevisionManager();
+ return (InternalCDORevision)revisionManager.getRevision(id, this, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE,
+ true);
+ }
+
+ public void changeTarget(CDOBranchPoint branchPoint, List<CDOID> invalidObjects,
+ List<CDORevisionDelta> allChangedObjects, List<CDOID> allDetachedObjects)
+ {
+ List<CDORevision> oldRevisions = getRevisions(invalidObjects);
+ setBranchPoint(branchPoint);
+ List<CDORevision> newRevisions = getRevisions(invalidObjects);
+
+ Iterator<CDORevision> it = newRevisions.iterator();
+ for (CDORevision oldRevision : oldRevisions)
+ {
+ CDORevision newRevision = it.next();
+ if (newRevision == null)
+ {
+ allDetachedObjects.add(oldRevision.getID());
+ }
+ else if (newRevision != oldRevision)
+ {
+ // Fix for Bugzilla 369646: ensure that revisions are fully loaded
+ ensureRevisionChunks((InternalCDORevision)newRevision);
+ ensureRevisionChunks((InternalCDORevision)oldRevision);
+
+ CDORevisionDelta delta = newRevision.compare(oldRevision);
+ allChangedObjects.add(delta);
+ }
+ }
+ }
+
+ // TODO: Eike can this be put in the Repository class?
+ /**
+ * Make sure that all lists of the given revision are fully loaded.
+ */
+ private void ensureRevisionChunks(InternalCDORevision revision)
+ {
+ for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(revision.getEClass()))
+ {
+ if (feature.isMany())
+ {
+ getRepository().ensureChunk(revision, feature, 0, revision.getList(feature).size());
+ }
+ }
+ }
+
+ private List<CDORevision> getRevisions(List<CDOID> ids)
+ {
+ return repository.getRevisionManager().getRevisions(ids, branchPoint, CDORevision.UNCHUNKED,
+ CDORevision.DEPTH_NONE, true);
+ }
+
+ public void setBranchPoint(CDOBranchPoint branchPoint)
+ {
+ checkOpen();
+ long timeStamp = branchPoint.getTimeStamp();
+ branchPoint = branchPoint.getBranch().getPoint(timeStamp);
+ validateTimeStamp(timeStamp);
+ this.branchPoint = branchPoint;
+ }
+
+ protected void validateTimeStamp(long timeStamp) throws IllegalArgumentException
+ {
+ if (timeStamp != UNSPECIFIED_DATE)
+ {
+ repository.validateTimeStamp(timeStamp);
+ }
+ }
+
+ public void setDurableLockingID(String durableLockingID)
+ {
+ this.durableLockingID = durableLockingID;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public synchronized void subscribe(CDOID id)
+ {
+ checkOpen();
+ changeSubscriptionIDs.add(id);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public synchronized void unsubscribe(CDOID id)
+ {
+ checkOpen();
+ changeSubscriptionIDs.remove(id);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public synchronized boolean hasSubscription(CDOID id)
+ {
+ checkOpen();
+ return changeSubscriptionIDs.contains(id);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public synchronized void clearChangeSubscription()
+ {
+ checkOpen();
+ changeSubscriptionIDs.clear();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return ObjectUtil.hashCode(sessionID, viewID);
+ }
+
+ @Override
+ public String toString()
+ {
+ int sessionID = session == null ? 0 : session.getSessionID();
+ return MessageFormat.format("{0}[{1}:{2}]", getClassName(), sessionID, viewID); //$NON-NLS-1$
+ }
+
+ protected String getClassName()
+ {
+ return "View"; //$NON-NLS-1$
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void close()
+ {
+ deactivate();
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ if (!isClosed())
+ {
+ session.viewClosed(this);
+ }
+
+ super.doDeactivate();
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void doClose()
+ {
+ clearChangeSubscription();
+ changeSubscriptionIDs = null;
+ session = null;
+ repository = null;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public boolean isClosed()
+ {
+ return repository == null;
+ }
+
+ private void checkOpen()
+ {
+ if (isClosed())
+ {
+ throw new IllegalStateException("View closed"); //$NON-NLS-1$
+ }
+ }
+
+ public IOptionsContainer getContainer()
+ {
+ return this;
+ }
+
+ public Options options()
+ {
+ return this;
+ }
+
+ public boolean isLockNotificationEnabled()
+ {
+ return lockNotificationsEnabled;
+ }
+
+ public void setLockNotificationEnabled(boolean enable)
+ {
+ lockNotificationsEnabled = enable;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java index a3c652424a..562881acdb 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java @@ -1,245 +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.spi.server; - -import org.eclipse.emf.cdo.common.branch.CDOBranch; -import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; -import org.eclipse.emf.cdo.common.commit.CDOChangeSetData; -import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; -import org.eclipse.emf.cdo.common.id.CDOID; -import org.eclipse.emf.cdo.common.lob.CDOLobHandler; -import org.eclipse.emf.cdo.common.protocol.CDODataOutput; -import org.eclipse.emf.cdo.common.revision.CDORevision; -import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; -import org.eclipse.emf.cdo.common.revision.CDORevisionKey; -import org.eclipse.emf.cdo.server.IQueryHandlerProvider; -import org.eclipse.emf.cdo.server.IRepository; -import org.eclipse.emf.cdo.server.IStoreAccessor; -import org.eclipse.emf.cdo.server.ITransaction; -import org.eclipse.emf.cdo.spi.common.CDOReplicationContext; -import org.eclipse.emf.cdo.spi.common.CDOReplicationInfo; -import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager; -import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager.BranchLoader; -import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo; -import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager; -import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager.CommitInfoLoader; -import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry; -import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry.PackageLoader; -import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry.PackageProcessor; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager.RevisionLoader; - -import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; -import org.eclipse.net4j.util.om.monitor.OMMonitor; - -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.spi.cdo.CDOSessionProtocol.LockObjectsResult; -import org.eclipse.emf.spi.cdo.CDOSessionProtocol.UnlockObjectsResult; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Semaphore; - -/** - * @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 InternalRepository extends IRepository, PackageProcessor, PackageLoader, BranchLoader, RevisionLoader, - CommitInfoLoader -{ - public void setName(String name); - - public void setType(Type type); - - public void setState(State state); - - public InternalStore getStore(); - - public void setStore(InternalStore store); - - public void setProperties(Map<String, String> properties); - - public InternalCDOBranchManager getBranchManager(); - - public void setBranchManager(InternalCDOBranchManager branchManager); - - /** - * @since 4.1 - */ - public Semaphore getPackageRegistryCommitLock(); - - /** - * Same as calling {@link #getPackageRegistry(boolean) getPackageRegistry(true)}. - */ - public InternalCDOPackageRegistry getPackageRegistry(); - - public InternalCDOPackageRegistry getPackageRegistry(boolean considerCommitContext); - - public InternalCDORevisionManager getRevisionManager(); - - public void setRevisionManager(InternalCDORevisionManager revisionManager); - - public InternalCDOCommitInfoManager getCommitInfoManager(); - - public InternalSessionManager getSessionManager(); - - public void setSessionManager(InternalSessionManager sessionManager); - - /** - * @deprecated As of 4.1 use {@link #getLockingManager()}. - */ - @Deprecated - public InternalLockManager getLockManager(); - - /** - * @since 4.1 - */ - public InternalLockManager getLockingManager(); - - public InternalQueryManager getQueryManager(); - - public void setQueryHandlerProvider(IQueryHandlerProvider queryHandlerProvider); - - public InternalCommitManager getCommitManager(); - - public InternalCommitContext createCommitContext(InternalTransaction transaction); - - /** - * Returns a commit time stamp that is guaranteed to be unique in this repository. At index 1 of the returned - * <code>long</code> array is the previous commit time. - * - * @since 4.0 - */ - public long[] createCommitTimeStamp(OMMonitor monitor); - - /** - * Like {@link #createCommitTimeStamp(OMMonitor)}, but forces the repository to use the timestamp value passed in as - * the argument. This should be called only to force the timestamp of the first commit of a new repository to be equal - * to its creation time. - * - * @since 4.0 - */ - public long[] forceCommitTimeStamp(long timestamp, OMMonitor monitor); - - /** - * Notifies the repository of the completion of a commit. The value passed in must be a value obtained earlier through - * {@link #createCommitTimeStamp(OMMonitor)} - * - * @since 4.0 - */ - public void endCommit(long timeStamp); - - /** - * Notifies the repository of the failure of a commit. The value passed in must be a value obtained earlier through - * {@link #createCommitTimeStamp(OMMonitor)} - * - * @since 4.0 - */ - public void failCommit(long timeStamp); - - /** - * @since 4.0 - */ - public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo); - - public void setRootResourceID(CDOID rootResourceID); - - /** - * @since 4.0 - */ - public void setLastCommitTimeStamp(long commitTimeStamp); - - /** - * @since 4.1 - */ - public void ensureChunks(InternalCDORevision revision); - - public IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature, int chunkStart, - int chunkEnd); - - public void notifyReadAccessHandlers(InternalSession session, CDORevision[] revisions, - List<CDORevision> additionalRevisions); - - public void notifyWriteAccessHandlers(ITransaction transaction, IStoreAccessor.CommitContext commitContext, - boolean beforeCommit, OMMonitor monitor); - - public void replicate(CDOReplicationContext context); - - public CDOReplicationInfo replicateRaw(CDODataOutput out, int lastReplicatedBranchID, long lastReplicatedCommitTime) - throws IOException; - - public CDOChangeSetData getChangeSet(CDOBranchPoint startPoint, CDOBranchPoint endPoint); - - /** - * @since 4.0 - */ - public Set<CDOID> getMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, - CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor); - - /** - * @since 4.0 - */ - public void queryLobs(List<byte[]> ids); - - /** - * @since 4.0 - */ - public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException; - - /** - * @since 4.0 - */ - public void loadLob(byte[] id, OutputStream out) throws IOException; - - /** - * @since 4.0 - */ - public void handleRevisions(EClass eClass, CDOBranch branch, boolean exactBranch, long timeStamp, boolean exactTime, - CDORevisionHandler handler); - - /** - * @since 4.0 - */ - public boolean isSkipInitialization(); - - /** - * @since 4.0 - */ - public void setSkipInitialization(boolean skipInitialization); - - /** - * @since 4.0 - */ - public void initSystemPackages(); - - /** - * @since 4.0 - */ - public void initMainBranch(InternalCDOBranchManager branchManager, long timeStamp); - - /** - * @since 4.1 - */ - public LockObjectsResult lock(InternalView view, LockType type, List<CDORevisionKey> keys, boolean recursive, - long timeout); - - /** - * @since 4.1 - */ - public UnlockObjectsResult unlock(InternalView view, LockType type, List<CDOID> ids, boolean recursive); -} +/*
+ * 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.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.server.IQueryHandlerProvider;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.spi.common.CDOReplicationContext;
+import org.eclipse.emf.cdo.spi.common.CDOReplicationInfo;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager.BranchLoader;
+import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager.CommitInfoLoader;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry.PackageLoader;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry.PackageProcessor;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager.RevisionLoader;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.LockObjectsResult;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.UnlockObjectsResult;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Semaphore;
+
+/**
+ * @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 InternalRepository extends IRepository, PackageProcessor, PackageLoader, BranchLoader, RevisionLoader,
+ CommitInfoLoader
+{
+ public void setName(String name);
+
+ public void setType(Type type);
+
+ public void setState(State state);
+
+ public InternalStore getStore();
+
+ public void setStore(InternalStore store);
+
+ public void setProperties(Map<String, String> properties);
+
+ public InternalCDOBranchManager getBranchManager();
+
+ public void setBranchManager(InternalCDOBranchManager branchManager);
+
+ /**
+ * @since 4.1
+ */
+ public Semaphore getPackageRegistryCommitLock();
+
+ /**
+ * Same as calling {@link #getPackageRegistry(boolean) getPackageRegistry(true)}.
+ */
+ public InternalCDOPackageRegistry getPackageRegistry();
+
+ public InternalCDOPackageRegistry getPackageRegistry(boolean considerCommitContext);
+
+ public InternalCDORevisionManager getRevisionManager();
+
+ public void setRevisionManager(InternalCDORevisionManager revisionManager);
+
+ public InternalCDOCommitInfoManager getCommitInfoManager();
+
+ public InternalSessionManager getSessionManager();
+
+ public void setSessionManager(InternalSessionManager sessionManager);
+
+ /**
+ * @deprecated As of 4.1 use {@link #getLockingManager()}.
+ */
+ @Deprecated
+ public InternalLockManager getLockManager();
+
+ /**
+ * @since 4.1
+ */
+ public InternalLockManager getLockingManager();
+
+ public InternalQueryManager getQueryManager();
+
+ public void setQueryHandlerProvider(IQueryHandlerProvider queryHandlerProvider);
+
+ public InternalCommitManager getCommitManager();
+
+ public InternalCommitContext createCommitContext(InternalTransaction transaction);
+
+ /**
+ * Returns a commit time stamp that is guaranteed to be unique in this repository. At index 1 of the returned
+ * <code>long</code> array is the previous commit time.
+ *
+ * @since 4.0
+ */
+ public long[] createCommitTimeStamp(OMMonitor monitor);
+
+ /**
+ * Like {@link #createCommitTimeStamp(OMMonitor)}, but forces the repository to use the timestamp value passed in as
+ * the argument. This should be called only to force the timestamp of the first commit of a new repository to be equal
+ * to its creation time.
+ *
+ * @since 4.0
+ */
+ public long[] forceCommitTimeStamp(long timestamp, OMMonitor monitor);
+
+ /**
+ * Notifies the repository of the completion of a commit. The value passed in must be a value obtained earlier through
+ * {@link #createCommitTimeStamp(OMMonitor)}
+ *
+ * @since 4.0
+ */
+ public void endCommit(long timeStamp);
+
+ /**
+ * Notifies the repository of the failure of a commit. The value passed in must be a value obtained earlier through
+ * {@link #createCommitTimeStamp(OMMonitor)}
+ *
+ * @since 4.0
+ */
+ public void failCommit(long timeStamp);
+
+ /**
+ * @since 4.0
+ */
+ public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo);
+
+ public void setRootResourceID(CDOID rootResourceID);
+
+ /**
+ * @since 4.0
+ */
+ public void setLastCommitTimeStamp(long commitTimeStamp);
+
+ public IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature, int chunkStart,
+ int chunkEnd);
+
+ public void notifyReadAccessHandlers(InternalSession session, CDORevision[] revisions,
+ List<CDORevision> additionalRevisions);
+
+ public void notifyWriteAccessHandlers(ITransaction transaction, IStoreAccessor.CommitContext commitContext,
+ boolean beforeCommit, OMMonitor monitor);
+
+ public void replicate(CDOReplicationContext context);
+
+ public CDOReplicationInfo replicateRaw(CDODataOutput out, int lastReplicatedBranchID, long lastReplicatedCommitTime)
+ throws IOException;
+
+ public CDOChangeSetData getChangeSet(CDOBranchPoint startPoint, CDOBranchPoint endPoint);
+
+ /**
+ * @since 4.0
+ */
+ public Set<CDOID> getMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo,
+ CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor);
+
+ /**
+ * @since 4.0
+ */
+ public void queryLobs(List<byte[]> ids);
+
+ /**
+ * @since 4.0
+ */
+ public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException;
+
+ /**
+ * @since 4.0
+ */
+ public void loadLob(byte[] id, OutputStream out) throws IOException;
+
+ /**
+ * @since 4.0
+ */
+ public void handleRevisions(EClass eClass, CDOBranch branch, boolean exactBranch, long timeStamp, boolean exactTime,
+ CDORevisionHandler handler);
+
+ /**
+ * @since 4.0
+ */
+ public boolean isSkipInitialization();
+
+ /**
+ * @since 4.0
+ */
+ public void setSkipInitialization(boolean skipInitialization);
+
+ /**
+ * @since 4.0
+ */
+ public void initSystemPackages();
+
+ /**
+ * @since 4.0
+ */
+ public void initMainBranch(InternalCDOBranchManager branchManager, long timeStamp);
+
+ /**
+ * @since 4.1
+ */
+ public LockObjectsResult lock(InternalView view, LockType type, List<CDORevisionKey> keys, boolean recursive,
+ long timeout);
+
+ /**
+ * @since 4.1
+ */
+ public UnlockObjectsResult unlock(InternalView view, LockType type, List<CDOID> ids, boolean recursive);
+}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java index ce4235b5f9..b9fef3935e 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java @@ -1,1633 +1,1632 @@ -/* - * 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; - -import org.eclipse.emf.cdo.CDOLock; -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.lock.CDOLockState; -import org.eclipse.emf.cdo.common.model.EMFUtil; -import org.eclipse.emf.cdo.common.revision.CDORevision; -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.cdo.view.CDOView; - -import org.eclipse.emf.internal.cdo.bundle.OM; -import org.eclipse.emf.internal.cdo.messages.Messages; -import org.eclipse.emf.internal.cdo.object.CDOLockImpl; -import org.eclipse.emf.internal.cdo.view.CDOStateMachine; - -import org.eclipse.net4j.util.ObjectUtil; -import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; -import org.eclipse.net4j.util.om.trace.ContextTracer; - -import org.eclipse.emf.common.notify.Adapter; -import org.eclipse.emf.common.notify.Notification; -import org.eclipse.emf.common.notify.NotificationChain; -import org.eclipse.emf.common.util.BasicEList; -import org.eclipse.emf.common.util.BasicEMap; -import org.eclipse.emf.common.util.ECollections; -import org.eclipse.emf.common.util.EList; -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.InternalEObject; -import org.eclipse.emf.ecore.impl.BasicEObjectImpl; -import org.eclipse.emf.ecore.impl.ENotificationImpl; -import org.eclipse.emf.ecore.impl.EStoreEObjectImpl; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.resource.Resource.Internal; -import org.eclipse.emf.ecore.util.DelegatingFeatureMap; -import org.eclipse.emf.ecore.util.EcoreEList; -import org.eclipse.emf.ecore.util.EcoreEMap; -import org.eclipse.emf.ecore.util.FeatureMap; -import org.eclipse.emf.ecore.util.FeatureMapUtil; -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.InternalCDOLoadable; -import org.eclipse.emf.spi.cdo.InternalCDOObject; -import org.eclipse.emf.spi.cdo.InternalCDOView; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -/** - * The base class of all <em>native</em> {@link CDOObject objects}. - * - * @author Eike Stepper - */ -public class CDOObjectImpl extends EStoreEObjectImpl implements InternalCDOObject -{ - private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_OBJECT, CDOObjectImpl.class); - - private CDOID id; - - private CDOState state; - - private InternalCDOView view; - - private InternalCDORevision revision; - - /** - * CDO uses this list instead of eSettings for transient objects. EMF uses eSettings as cache. CDO deactivates the - * cache but EMF still used eSettings to store list wrappers. CDO needs another place to store the real list with the - * actual data (transient mode) and accessible through EStore. This allows CDO to always use the same instance of the - * list wrapper. - */ - private transient Object[] cdoSettings; - - public CDOObjectImpl() - { - state = CDOState.TRANSIENT; - eContainer = null; - cdoSettings = null; - } - - public CDOID cdoID() - { - return id; - } - - public CDOState cdoState() - { - return state; - } - - /** - * @since 2.0 - */ - public InternalCDORevision cdoRevision() - { - return revision; - } - - /** - * @since 2.0 - */ - public InternalCDOView cdoView() - { - return view; - } - - public CDOResourceImpl cdoResource() - { - Resource resource = eResource(); - if (resource instanceof CDOResourceImpl) - { - return (CDOResourceImpl)resource; - } - - return null; - } - - /** - * @since 2.0 - */ - public CDOResourceImpl cdoDirectResource() - { - Resource.Internal resource = eDirectResource(); - if (resource instanceof CDOResourceImpl) - { - return (CDOResourceImpl)resource; - } - - return null; - } - - /** - * @since 3.0 - */ - public void cdoPrefetch(int depth) - { - view.prefetchRevisions(id, depth); - } - - public void cdoReload() - { - CDOStateMachine.INSTANCE.reload(this); - } - - /** - * @since 2.0 - */ - public boolean cdoConflict() - { - return FSMUtil.isConflict(this); - } - - /** - * @since 2.0 - */ - public boolean cdoInvalid() - { - return FSMUtil.isInvalid(this); - } - - /** - * @since 2.0 - */ - public CDOLock cdoReadLock() - { - return createLock(this, LockType.READ); - } - - /** - * @since 2.0 - */ - public CDOLock cdoWriteLock() - { - return createLock(this, LockType.WRITE); - } - - /** - * @since 4.1 - */ - public CDOLock cdoWriteOption() - { - return createLock(this, LockType.OPTION); - } - - /** - * @since 4.1 - */ - public CDOLockState cdoLockState() - { - return getLockState(this); - } - - public void cdoInternalSetID(CDOID id) - { - if (TRACER.isEnabled()) - { - TRACER.format("Setting ID: {0}", id); //$NON-NLS-1$ - } - - this.id = id; - } - - public CDOState cdoInternalSetState(CDOState state) - { - CDOState oldState = this.state; - if (oldState != state) - { - if (TRACER.isEnabled()) - { - TRACER.format("Setting state {0} for {1}", state, this); //$NON-NLS-1$ - } - - this.state = state; - if (view != null) - { - view.handleObjectStateChanged(this, oldState, state); - } - - return oldState; - } - - return null; - } - - /** - * @since 2.0 - */ - public void cdoInternalSetRevision(CDORevision revision) - { - if (TRACER.isEnabled()) - { - TRACER.format("Setting revision: {0}", revision); //$NON-NLS-1$ - } - - this.revision = (InternalCDORevision)revision; - } - - /** - * @since 2.0 - */ - public void cdoInternalSetView(CDOView view) - { - this.view = (InternalCDOView)view; - if (this.view != null) - { - eSetStore(this.view.getStore()); - } - else - { - eSetStore(null); - } - } - - public void cdoInternalSetResource(CDOResource resource) - { - throw new UnsupportedOperationException(); - } - - /** - * @since 2.0 - */ - public void cdoInternalPreLoad() - { - // Do nothing - } - - public void cdoInternalPostLoad() - { - // Reset EMAP objects - if (eSettings != null) - { - // Make sure transient features are kept but persisted values are not cached. - EClass eClass = eClass(); - for (int i = 0; i < eClass.getFeatureCount(); i++) - { - EStructuralFeature eFeature = cdoInternalDynamicFeature(i); - - // We need to keep the existing list if possible. - if (EMFUtil.isPersistent(eFeature) && eSettings[i] instanceof InternalCDOLoadable) - { - ((InternalCDOLoadable)eSettings[i]).cdoInternalPostLoad(); - } - } - } - } - - /** - * @since 2.0 - */ - public void cdoInternalPostInvalidate() - { - // Do nothing - } - - public void cdoInternalPostAttach() - { - if (TRACER.isEnabled()) - { - TRACER.format("Populating revision for {0}", this); //$NON-NLS-1$ - } - - revision.setContainerID(eContainer == null ? CDOID.NULL : view.convertObjectToID(eContainer, true)); - revision.setContainingFeatureID(eContainerFeatureID); - - Resource directResource = eDirectResource(); - if (directResource instanceof CDOResource) - { - CDOResource cdoResource = (CDOResource)directResource; - revision.setResourceID(cdoResource.cdoID()); - } - - if (cdoSettings != null) - { - EClass eClass = eClass(); - for (int i = 0; i < eClass.getFeatureCount(); i++) - { - EStructuralFeature eFeature = cdoInternalDynamicFeature(i); - if (EMFUtil.isPersistent(eFeature)) - { - instanceToRevisionFeature(view, this, eFeature, cdoSettings[i]); - } - } - - cdoRevision().setUnchunked(); - cdoSettings = null; - } - } - - /** - * It is really important for accessing the data to go through {@link #cdoStore()}. {@link #eStore()} will redirect - * you to the transient data. - * - * @since 2.0 - */ - public void cdoInternalPostDetach(boolean remote) - { - if (remote) - { - // Do nothing - return; - } - - if (TRACER.isEnabled()) - { - TRACER.format("Depopulating revision for {0}", this); //$NON-NLS-1$ - } - - CDOStore store = cdoStore(); - super.eSetDirectResource((Resource.Internal)store.getResource(this)); - eContainer = store.getContainer(this); - eContainerFeatureID = store.getContainingFeatureID(this); - - // Ensure that the internal eSettings array is initialized; - resetSettings(); - - EClass eClass = eClass(); - for (int i = 0; i < eClass.getFeatureCount(); i++) - { - EStructuralFeature eFeature = cdoInternalDynamicFeature(i); - if (EMFUtil.isPersistent(eFeature)) - { - revisionToInstanceFeature(this, revision, eFeature); - } - } - } - - /** - * @since 3.0 - */ - public void cdoInternalPostRollback() - { - // Do nothing - } - - public void cdoInternalPreCommit() - { - // Do nothing - } - - public InternalEObject cdoInternalInstance() - { - return this; - } - - public EStructuralFeature cdoInternalDynamicFeature(int dynamicFeatureID) - { - return eDynamicFeature(dynamicFeatureID); - } - - /** - * @since 2.0 - */ - @Override - public synchronized EList<Adapter> eAdapters() - { - if (eAdapters == null) - { - // TODO Adjust for EObjectEAdapterList (see bug #247130) - eAdapters = new EAdapterList<Adapter>(this) - { - private static final long serialVersionUID = 1L; - - @Override - protected void didAdd(int index, Adapter newObject) - { - if (view == null || view.isActive()) - { - super.didAdd(index, newObject); - if (!FSMUtil.isTransient(CDOObjectImpl.this)) - { - view.handleAddAdapter(CDOObjectImpl.this, newObject); - } - } - } - - @Override - protected void didRemove(int index, Adapter oldObject) - { - if (view == null || view.isActive()) - { - super.didRemove(index, oldObject); - if (!FSMUtil.isTransient(CDOObjectImpl.this)) - { - view.handleRemoveAdapter(CDOObjectImpl.this, oldObject); - } - } - } - }; - } - - return eAdapters; - } - - /** - * @since 2.0 - */ - @Override - public Resource.Internal eDirectResource() - { - if (FSMUtil.isTransient(this)) - { - return super.eDirectResource(); - } - - return (Resource.Internal)cdoStore().getResource(this); - } - - @Override - public Resource.Internal eInternalResource() - { - if (FSMUtil.isInvalid(this)) - { - return null; - } - - return super.eInternalResource(); - } - - @Override - public Object dynamicGet(int dynamicFeatureID) - { - Object result = eSettings[dynamicFeatureID]; - if (result == null) - { - EStructuralFeature eStructuralFeature = eDynamicFeature(dynamicFeatureID); - if (EMFUtil.isPersistent(eStructuralFeature)) - { - if (FeatureMapUtil.isFeatureMap(eStructuralFeature)) - { - eSettings[dynamicFeatureID] = result = createFeatureMap(eStructuralFeature); - } - else if (eStructuralFeature.isMany()) - { - eSettings[dynamicFeatureID] = result = createList(eStructuralFeature); - } - else - { - result = eStore().get(this, eStructuralFeature, EStore.NO_INDEX); - if (eIsCaching()) - { - eSettings[dynamicFeatureID] = result; - } - } - } - } - - return result; - } - - @Override - public void dynamicSet(int dynamicFeatureID, Object value) - { - EStructuralFeature eStructuralFeature = eDynamicFeature(dynamicFeatureID); - if (!EMFUtil.isPersistent(eStructuralFeature)) - { - eSettings[dynamicFeatureID] = value; - } - else - { - eStore().set(this, eStructuralFeature, EStore.NO_INDEX, value); - if (eIsCaching()) - { - eSettings[dynamicFeatureID] = value; - } - } - } - - @Override - public void dynamicUnset(int dynamicFeatureID) - { - EStructuralFeature eStructuralFeature = eDynamicFeature(dynamicFeatureID); - if (!EMFUtil.isPersistent(eStructuralFeature)) - { - eSettings[dynamicFeatureID] = null; - } - else - { - eStore().unset(this, eDynamicFeature(dynamicFeatureID)); - if (eIsCaching()) - { - eSettings[dynamicFeatureID] = null; - } - } - } - - /** - * @since 2.0 - */ - @Override - protected boolean eDynamicIsSet(int dynamicFeatureID, EStructuralFeature eFeature) - { - if (dynamicFeatureID < 0) - { - return eOpenIsSet(eFeature); - } - - if (EMFUtil.isPersistent(eFeature)) - { - return eStore().isSet(this, eFeature); - } - - return eSettingDelegate(eFeature).dynamicIsSet(this, eSettings(), dynamicFeatureID); - } - - /** - * @since 2.0 - */ - @Override - public EStore eStore() - { - if (FSMUtil.isTransient(this)) - { - return CDOStoreSettingsImpl.INSTANCE; - } - - return cdoStore(); - } - - @Override - public InternalEObject eInternalContainer() - { - InternalEObject container; - if (FSMUtil.isTransient(this)) - { - container = eContainer; - } - else - { - // Delegate to CDOStore - container = cdoStore().getContainer(this); - } - - return container; - } - - @Override - public int eContainerFeatureID() - { - if (FSMUtil.isTransient(this)) - { - return eContainerFeatureID; - } - - // Delegate to CDOStore - return cdoStore().getContainingFeatureID(this); - } - - /** - * Code took from {@link BasicEObjectImpl#eBasicSetContainer} and modify it to detect when object are moved in the - * same context. (E.g.: An object is moved from resA to resB. resA and resB belongs to the same CDORepositoryInfo. - * Without this special handling, a detach and newObject will be generated for the object moved) - * - * @since 2.0 - */ - @Override - public NotificationChain eBasicSetContainer(InternalEObject newContainer, int newContainerFeatureID, - NotificationChain msgs) - { - boolean isResourceRoot = this instanceof CDOResource && ((CDOResource)this).isRoot(); - - InternalEObject oldContainer = eInternalContainer(); - Resource.Internal oldResource = eDirectResource(); - Resource.Internal newResource = null; - if (oldResource != null) - { - if (newContainer != null && !eContainmentFeature(this, newContainer, newContainerFeatureID).isResolveProxies()) - { - msgs = ((InternalEList<?>)oldResource.getContents()).basicRemove(this, msgs); - eSetDirectResource(null); - newResource = newContainer.eInternalResource(); - } - else - { - oldResource = null; - } - } - else - { - if (oldContainer != null) - { - oldResource = oldContainer.eInternalResource(); - } - - if (newContainer != null) - { - newResource = newContainer.eInternalResource(); - } - } - - CDOView oldView = view; - CDOView newView = newResource != null && newResource instanceof CDOResource ? ((CDOResource)newResource).cdoView() - : null; - - boolean moved = oldView != null && oldView == newView; - if (!moved && oldResource != null && !isResourceRoot) - { - oldResource.detached(this); - } - - int oldContainerFeatureID = eContainerFeatureID(); - eBasicSetContainer(newContainer, newContainerFeatureID); - - if (!moved && oldResource != newResource && newResource != null) - { - newResource.attached(this); - } - - if (eNotificationRequired()) - { - if (oldContainer != null && oldContainerFeatureID >= 0 && oldContainerFeatureID != newContainerFeatureID) - { - ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, oldContainerFeatureID, - oldContainer, null); - if (msgs == null) - { - msgs = notification; - } - else - { - msgs.add(notification); - } - } - - if (newContainerFeatureID >= 0) - { - ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, newContainerFeatureID, - oldContainerFeatureID == newContainerFeatureID ? oldContainer : null, newContainer); - if (msgs == null) - { - msgs = notification; - } - else - { - msgs.add(notification); - } - } - } - - return msgs; - } - - /** - * Code took from {@link BasicEObjectImpl#eSetResource} and modify it to detect when object are moved in the same - * context. - * - * @since 2.0 - */ - @Override - public NotificationChain eSetResource(Resource.Internal resource, NotificationChain notifications) - { - Resource.Internal oldResource = eDirectResource(); - - CDOView oldView = view; - CDOView newView = resource != null && resource instanceof CDOResource ? ((CDOResource)resource).cdoView() : null; - - boolean isSameView; - if (state == CDOState.NEW) - { - isSameView = false; - } - else - { - isSameView = oldView != null && oldView == newView; - } - - if (oldResource != null) - { - notifications = ((InternalEList<?>)oldResource.getContents()).basicRemove(this, notifications); - - // When setting the resource to null we assume that detach has already been called in the resource implementation - if (!isSameView && resource != null) - { - oldResource.detached(this); - } - } - - InternalEObject oldContainer = eInternalContainer(); - if (oldContainer != null && !isSameView) - { - if (eContainmentFeature().isResolveProxies()) - { - Resource.Internal oldContainerResource = oldContainer.eInternalResource(); - if (oldContainerResource != null) - { - // If we're not setting a new resource, attach it to the old container's resource. - if (resource == null) - { - oldContainerResource.attached(this); - } - - // If we didn't detach it from an old resource already, detach it from the old container's resource. - // - else if (oldResource == null) - { - oldContainerResource.detached(this); - } - } - } - else - { - notifications = eBasicRemoveFromContainer(notifications); - notifications = eBasicSetContainer(null, -1, notifications); - } - } - - eSetDirectResource(resource); - - return notifications; - } - - /** - * Specializing the behaviour of {@link #hashCode()} is not permitted as per {@link EObject} specification. - */ - @Override - public final int hashCode() - { - return super.hashCode(); - } - - /** - * Specializing the behaviour of {@link #equals(Object)} is not permitted as per {@link EObject} specification. - */ - @Override - public final boolean equals(Object obj) - { - return super.equals(obj); - } - - @Override - public String toString() - { - if (id == null) - { - return eClass().getName() + "?"; //$NON-NLS-1$ - } - - return eClass().getName() + "@" + id; //$NON-NLS-1$ - } - - /** - * @since 2.0 - */ - protected Object[] cdoSettings() - { - if (cdoSettings == null) - { - int size = eClass().getFeatureCount() - eStaticFeatureCount(); - if (size == 0) - { - cdoSettings = ENO_SETTINGS; - } - else - { - cdoSettings = new Object[size]; - } - } - - return cdoSettings; - } - - /** - * @since 2.0 - */ - protected Object[] cdoBasicSettings() - { - return cdoSettings; - } - - @Override - protected FeatureMap createFeatureMap(EStructuralFeature eStructuralFeature) - { - return new CDOStoreFeatureMap(eStructuralFeature); - } - - /** - * @since 4.1 - */ - protected CDOStoreEcoreEMap createMap(EStructuralFeature eStructuralFeature) - { - return new CDOStoreEcoreEMap(eStructuralFeature); - } - - /** - * @since 4.1 - */ - protected CDOStoreUnorderedEList<Object> createUnorderedList(EStructuralFeature eStructuralFeature) - { - return new CDOStoreUnorderedEList<Object>(eStructuralFeature); - } - - @Override - protected EList<?> createList(EStructuralFeature eStructuralFeature) - { - if (isMap(eStructuralFeature)) - { - return createMap(eStructuralFeature); - } - - if (!eStructuralFeature.isOrdered()) - { - return createUnorderedList(eStructuralFeature); - } - - return super.createList(eStructuralFeature); - } - - private boolean isMap(EStructuralFeature eStructuralFeature) - { - // Answer from Christian Damus: - // Java ensures that string constants are interned, so this is actually - // more efficient than .equals() and it's correct - return eStructuralFeature.getEType().getInstanceClassName() == "java.util.Map$Entry"; //$NON-NLS-1$ - } - - @Override - protected void eInitializeContainer() - { - throw new UnsupportedOperationException(); - } - - @Override - protected void eSetDirectResource(Internal resource) - { - if (FSMUtil.isTransient(this)) - { - super.eSetDirectResource(resource); - } - else if (resource instanceof CDOResourceImpl || resource == null) - { - cdoStore().setContainer(this, (CDOResourceImpl)resource, eInternalContainer(), eContainerFeatureID()); - } - else - { - throw new IllegalArgumentException(Messages.getString("CDOObjectImpl.8")); //$NON-NLS-1$ - } - } - - /** - * Don't cache non-transient features in this CDOObject's {@link #eSettings()}. - */ - @Override - protected boolean eIsCaching() - { - return false; - } - - @Override - protected void eBasicSetContainer(InternalEObject newEContainer, int newContainerFeatureID) - { - if (TRACER.isEnabled()) - { - TRACER.format("Setting container: {0}, featureID={1}", newEContainer, newContainerFeatureID); //$NON-NLS-1$ - } - - if (FSMUtil.isTransient(this)) - { - super.eBasicSetContainer(newEContainer, newContainerFeatureID); - } - else - { - cdoStore().setContainer(this, cdoDirectResource(), newEContainer, newContainerFeatureID); - } - } - - private CDOStore cdoStore() - { - return view.getStore(); - } - - private void resetSettings() - { - cdoSettings = null; - cdoSettings(); - } - - /** - * Adjust the reference ONLY if the opposite reference used CDOID. This is true ONLY if the state of <cdo>this</code> - * was not {@link CDOState#NEW}. - */ - private static void adjustOppositeReference(InternalCDOObject instance, InternalEObject object, EReference feature) - { - if (object != null) - { - InternalCDOObject cdoObject = (InternalCDOObject)CDOUtil.getCDOObject(object); - if (cdoObject != null && !FSMUtil.isTransient(cdoObject)) - { - if (feature.isMany()) - { - int index = cdoObject.eStore().indexOf(cdoObject, feature, instance.cdoID()); - - // TODO Simon Log an error in the new view.getErrors() in the case we are not able to find the object. - // Cannot throw an exception, the detach process is too far. - if (index != -1) - { - cdoObject.eStore().set(cdoObject, feature, index, instance); - } - } - else - { - cdoObject.eStore().set(cdoObject, feature, 0, instance); - } - } - else - { - if (feature.isResolveProxies()) - { - // We should not trigger events. But we have no choice :-(. - if (feature.isMany()) - { - @SuppressWarnings("unchecked") - InternalEList<Object> list = (InternalEList<Object>)object.eGet(feature); - int index = list.indexOf(instance); - if (index != -1) - { - list.set(index, instance); - } - } - else - { - object.eSet(feature, instance); - } - } - } - } - } - - /** - * @since 2.0 - */ - public static void revisionToInstanceFeature(InternalCDOObject instance, InternalCDORevision revision, - EStructuralFeature eFeature) - { - if (TRACER.isEnabled()) - { - TRACER.format("Depopulating feature {0}", eFeature); //$NON-NLS-1$ - } - - EStructuralFeature.Internal internalFeature = (EStructuralFeature.Internal)eFeature; - InternalCDOView view = instance.cdoView(); - EReference oppositeReference = view.isObjectNew(instance.cdoID()) ? null : internalFeature.getEOpposite(); - - CDOStore cdoStore = view.getStore(); - EStore eStore = instance.eStore(); - - if (eFeature.isMany()) - { - int size = cdoStore.size(instance, eFeature); - for (int index = 0; index < size; index++) - { - // Do not trigger events - // Do not trigger inverse updates - Object object = cdoStore.get(instance, eFeature, index); - eStore.add(instance, eFeature, index, object); - if (oppositeReference != null) - { - adjustOppositeReference(instance, (InternalEObject)object, oppositeReference); - } - } - } - else - { - Object object = cdoStore.get(instance, eFeature, EStore.NO_INDEX); - eStore.set(instance, eFeature, EStore.NO_INDEX, object); - if (oppositeReference != null) - { - adjustOppositeReference(instance, (InternalEObject)object, oppositeReference); - } - } - } - - /** - * @since 3.0 - */ - public static void instanceToRevisionFeature(InternalCDOView view, InternalCDOObject object, - EStructuralFeature feature, Object setting) - { - if (TRACER.isEnabled()) - { - TRACER.format("Populating feature {0}", feature); //$NON-NLS-1$ - } - - CDOStore cdoStore = view.getStore(); - InternalCDORevision revision = object.cdoRevision(); - - if (feature.isMany()) - { - if (setting != null) - { - int index = 0; - @SuppressWarnings("unchecked") - EList<Object> list = (EList<Object>)setting; - for (Object value : list) - { - value = cdoStore.convertToCDO(object, feature, value); - revision.add(feature, index++, value); - } - } - } - else - { - setting = cdoStore.convertToCDO(object, feature, setting); - revision.set(feature, 0, setting); - } - } - - /** - * @since 4.1 - */ - public static CDOLock createLock(InternalCDOObject object, LockType type) - { - if (FSMUtil.isTransient(object)) - { - throw new IllegalStateException("Call CDOView.lockObjects() for transient object " + object); - } - - return new CDOLockImpl(object, type); - } - - /** - * @since 4.1 - */ - public static CDOLockState getLockState(InternalCDOObject object) - { - if (!FSMUtil.isTransient(object)) - { - InternalCDOView view = object.cdoView(); - CDOID id = object.cdoID(); - - return view.getLockStates(Collections.singletonList(id))[0]; - } - - return null; - } - - /** - * For internal use only. - * - * @author Simon McDuff - * @since 2.0 - */ - public static class CDOStoreSettingsImpl implements InternalEObject.EStore - { - public static CDOStoreSettingsImpl INSTANCE = new CDOStoreSettingsImpl(); - - private CDOStoreSettingsImpl() - { - } - - protected Object getValue(InternalEObject eObject, int dynamicFeatureID) - { - Object value = ((CDOObjectImpl)eObject).cdoSettings()[dynamicFeatureID]; - return value; - } - - protected EList<Object> getValueAsList(InternalEObject eObject, int dynamicFeatureID) - { - @SuppressWarnings("unchecked") - EList<Object> result = (EList<Object>)getValue(eObject, dynamicFeatureID); - if (result == null) - { - result = new BasicEList<Object>(); - ((CDOObjectImpl)eObject).cdoSettings()[dynamicFeatureID] = result; - } - - return result; - } - - protected Object setValue(InternalEObject eObject, int dynamicFeatureID, Object newValue) - { - Object settings[] = ((CDOObjectImpl)eObject).cdoSettings(); - Object oldSetting = settings[dynamicFeatureID]; - settings[dynamicFeatureID] = newValue; - return oldSetting; - } - - protected int eDynamicFeatureID(InternalEObject eObject, EStructuralFeature feature) - { - return ((CDOObjectImpl)eObject).eDynamicFeatureID(feature); - } - - public Object get(InternalEObject eObject, EStructuralFeature feature, int index) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - if (index != NO_INDEX) - { - return getValueAsList(eObject, dynamicFeatureID).get(index); - } - - return getValue(eObject, dynamicFeatureID); - } - - public Object set(InternalEObject eObject, EStructuralFeature feature, int index, Object value) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - if (index != NO_INDEX) - { - return getValueAsList(eObject, dynamicFeatureID).set(index, value); - } - - return setValue(eObject, dynamicFeatureID, value); - } - - public void add(InternalEObject eObject, EStructuralFeature feature, int index, Object value) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - getValueAsList(eObject, dynamicFeatureID).add(index, value); - } - - public Object remove(InternalEObject eObject, EStructuralFeature feature, int index) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - return getValueAsList(eObject, dynamicFeatureID).remove(index); - } - - public Object move(InternalEObject eObject, EStructuralFeature feature, int targetIndex, int sourceIndex) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - return getValueAsList(eObject, dynamicFeatureID).move(targetIndex, sourceIndex); - } - - public void clear(InternalEObject eObject, EStructuralFeature feature) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - if (feature.isMany()) - { - getValueAsList(eObject, dynamicFeatureID).clear(); - } - - setValue(eObject, dynamicFeatureID, null); - } - - public int size(InternalEObject eObject, EStructuralFeature feature) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - return getValueAsList(eObject, dynamicFeatureID).size(); - } - - public int indexOf(InternalEObject eObject, EStructuralFeature feature, Object value) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - return getValueAsList(eObject, dynamicFeatureID).indexOf(value); - } - - public int lastIndexOf(InternalEObject eObject, EStructuralFeature feature, Object value) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - return getValueAsList(eObject, dynamicFeatureID).lastIndexOf(value); - } - - public Object[] toArray(InternalEObject eObject, EStructuralFeature feature) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - return getValueAsList(eObject, dynamicFeatureID).toArray(); - } - - public <T> T[] toArray(InternalEObject eObject, EStructuralFeature feature, T[] array) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - return getValueAsList(eObject, dynamicFeatureID).toArray(array); - } - - public boolean isEmpty(InternalEObject eObject, EStructuralFeature feature) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - return getValueAsList(eObject, dynamicFeatureID).isEmpty(); - } - - public boolean contains(InternalEObject eObject, EStructuralFeature feature, Object value) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - return getValueAsList(eObject, dynamicFeatureID).contains(value); - } - - public int hashCode(InternalEObject eObject, EStructuralFeature feature) - { - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - return getValueAsList(eObject, dynamicFeatureID).hashCode(); - } - - public InternalEObject getContainer(InternalEObject eObject) - { - return null; - } - - public EStructuralFeature getContainingFeature(InternalEObject eObject) - { - throw new UnsupportedOperationException("Should never be called"); - } - - public EObject create(EClass eClass) - { - return new EStoreEObjectImpl(eClass, this); - } - - public boolean isSet(InternalEObject eObject, EStructuralFeature feature) - { - if (!feature.isUnsettable()) - { - if (feature.isMany()) - { - @SuppressWarnings("unchecked") - InternalEList<Object> list = (InternalEList<Object>)eObject.eGet(feature); - return list != null && !list.isEmpty(); - } - - return !ObjectUtil.equals(eObject.eGet(feature), feature.getDefaultValue()); - } - - Object[] settings = ((CDOObjectImpl)eObject).cdoBasicSettings(); - if (settings == null) - { - return false; - } - - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - return settings[dynamicFeatureID] != null; - } - - public void unset(InternalEObject eObject, EStructuralFeature feature) - { - Object[] settings = ((CDOObjectImpl)eObject).cdoBasicSettings(); - if (settings == null) - { - // Is already unset - return; - } - - int dynamicFeatureID = eDynamicFeatureID(eObject, feature); - if (feature.isUnsettable()) - { - settings[dynamicFeatureID] = null; - } - else - { - settings[dynamicFeatureID] = feature.getDefaultValue(); - } - } - } - - /** - * @author Eike Stepper - * @since 4.1 - */ - public class CDOStoreEcoreEMap extends EcoreEMap<Object, Object> implements InternalCDOLoadable - { - private static final long serialVersionUID = 1L; - - public CDOStoreEcoreEMap(EStructuralFeature eStructuralFeature) - { - super((EClass)eStructuralFeature.getEType(), BasicEMap.Entry.class, null); - delegateEList = new BasicEStoreEList<BasicEMap.Entry<Object, Object>>(CDOObjectImpl.this, eStructuralFeature) - { - private static final long serialVersionUID = 1L; - - @Override - public void unset() - { - super.unset(); - doClear(); - } - - @Override - protected void didAdd(int index, BasicEMap.Entry<Object, Object> newObject) - { - CDOStoreEcoreEMap.this.doPut(newObject); - } - - @Override - protected void didSet(int index, BasicEMap.Entry<Object, Object> newObject, - BasicEMap.Entry<Object, Object> oldObject) - { - didRemove(index, oldObject); - didAdd(index, newObject); - } - - @Override - protected void didRemove(int index, BasicEMap.Entry<Object, Object> oldObject) - { - CDOStoreEcoreEMap.this.doRemove(oldObject); - } - - @Override - protected void didClear(int size, Object[] oldObjects) - { - CDOStoreEcoreEMap.this.doClear(); - } - - @Override - protected void didMove(int index, BasicEMap.Entry<Object, Object> movedObject, int oldIndex) - { - CDOStoreEcoreEMap.this.doMove(movedObject); - } - }; - - size = delegateEList.size(); - } - - private void checkListForReading() - { - if (!FSMUtil.isTransient(CDOObjectImpl.this)) - { - CDOStateMachine.INSTANCE.read(CDOObjectImpl.this); - } - } - - /** - * Ensures that the entry data is created and is populated with contents of the delegate list. - */ - @Override - protected synchronized void ensureEntryDataExists() - { - checkListForReading(); - super.ensureEntryDataExists(); - } - - @Override - public int size() - { - checkListForReading(); - return size; - } - - @Override - public boolean isEmpty() - { - checkListForReading(); - return size == 0; - } - - @Override - public boolean contains(Object object) - { - checkListForReading(); - return super.contains(object); - } - - @Override - public boolean containsAll(Collection<?> collection) - { - checkListForReading(); - return super.containsAll(collection); - } - - @Override - public boolean containsKey(Object key) - { - checkListForReading(); - return super.containsKey(key); - } - - @Override - public boolean containsValue(Object value) - { - checkListForReading(); - return super.containsValue(value); - } - - public void cdoInternalPostLoad() - { - entryData = null; - size = delegateEList.size(); - } - - public void cdoInternalPreLoad() - { - } - } - - /** - * @author Andras Peteri - * @since 4.1 - */ - public class CDOStoreUnorderedEList<E> extends BasicEStoreEList<E> - { - private static final long serialVersionUID = 1L; - - public CDOStoreUnorderedEList(EStructuralFeature feature) - { - super(CDOObjectImpl.this, feature); - } - - @Override - public E remove(int index) - { - boolean oldObjectIsLast = index == size() - 1; - E oldObject = super.remove(index); - - if (!oldObjectIsLast) - { - move(index, size() - 1); - } - - return oldObject; - } - } - - /** - * TODO Remove this when EMF has fixed bug 197487 - * - * @author Eike Stepper - */ - public class CDOStoreFeatureMap extends DelegatingFeatureMap - { - private static final long serialVersionUID = 1L; - - public CDOStoreFeatureMap(EStructuralFeature eStructuralFeature) - { - super(CDOObjectImpl.this, eStructuralFeature); - } - - @Override - protected List<FeatureMap.Entry> delegateList() - { - throw new UnsupportedOperationException(); - } - - @Override - public EStructuralFeature getEStructuralFeature() - { - return eStructuralFeature; - } - - @Override - protected void delegateAdd(int index, Entry object) - { - eStore().add(owner, eStructuralFeature, index, object); - } - - @Override - protected void delegateAdd(Entry object) - { - delegateAdd(delegateSize(), object); - } - - @Override - protected List<FeatureMap.Entry> delegateBasicList() - { - int size = delegateSize(); - if (size == 0) - { - return ECollections.emptyEList(); - } - - Object[] data = cdoStore().toArray(owner, eStructuralFeature); - return new EcoreEList.UnmodifiableEList<FeatureMap.Entry>(owner, eStructuralFeature, data.length, data); - } - - @Override - protected void delegateClear() - { - eStore().clear(owner, eStructuralFeature); - } - - @Override - protected boolean delegateContains(Object object) - { - return eStore().contains(owner, eStructuralFeature, object); - } - - @Override - protected boolean delegateContainsAll(Collection<?> collection) - { - for (Object o : collection) - { - if (!delegateContains(o)) - { - return false; - } - } - - return true; - } - - @Override - protected Entry delegateGet(int index) - { - return (Entry)eStore().get(owner, eStructuralFeature, index); - } - - @Override - protected int delegateHashCode() - { - return eStore().hashCode(owner, eStructuralFeature); - } - - @Override - protected int delegateIndexOf(Object object) - { - return eStore().indexOf(owner, eStructuralFeature, object); - } - - @Override - protected boolean delegateIsEmpty() - { - return eStore().isEmpty(owner, eStructuralFeature); - } - - @Override - protected Iterator<FeatureMap.Entry> delegateIterator() - { - return iterator(); - } - - @Override - protected int delegateLastIndexOf(Object object) - { - return eStore().lastIndexOf(owner, eStructuralFeature, object); - } - - @Override - protected ListIterator<FeatureMap.Entry> delegateListIterator() - { - return listIterator(); - } - - @Override - protected Entry delegateRemove(int index) - { - return (Entry)eStore().remove(owner, eStructuralFeature, index); - } - - @Override - protected Entry delegateSet(int index, Entry object) - { - return (Entry)eStore().set(owner, eStructuralFeature, index, object); - } - - @Override - protected int delegateSize() - { - return eStore().size(owner, eStructuralFeature); - } - - @Override - protected Object[] delegateToArray() - { - return eStore().toArray(owner, eStructuralFeature); - } - - @Override - protected <T> T[] delegateToArray(T[] array) - { - return eStore().toArray(owner, eStructuralFeature, array); - } - - @Override - protected Entry delegateMove(int targetIndex, int sourceIndex) - { - return (Entry)eStore().move(owner, eStructuralFeature, targetIndex, sourceIndex); - } - - @Override - protected String delegateToString() - { - StringBuffer stringBuffer = new StringBuffer(); - stringBuffer.append("["); //$NON-NLS-1$ - for (int i = 0, size = size(); i < size;) - { - Object value = delegateGet(i); - stringBuffer.append(String.valueOf(value)); - if (++i < size) - { - stringBuffer.append(", "); //$NON-NLS-1$ - } - } - - stringBuffer.append("]"); //$NON-NLS-1$ - return stringBuffer.toString(); - } - } -} +/*
+ * 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;
+
+import org.eclipse.emf.cdo.CDOLock;
+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.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+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.cdo.view.CDOView;
+
+import org.eclipse.emf.internal.cdo.bundle.OM;
+import org.eclipse.emf.internal.cdo.messages.Messages;
+import org.eclipse.emf.internal.cdo.object.CDOLockImpl;
+import org.eclipse.emf.internal.cdo.view.CDOStateMachine;
+
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.NotificationChain;
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.BasicEMap;
+import org.eclipse.emf.common.util.ECollections;
+import org.eclipse.emf.common.util.EList;
+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.InternalEObject;
+import org.eclipse.emf.ecore.impl.BasicEObjectImpl;
+import org.eclipse.emf.ecore.impl.ENotificationImpl;
+import org.eclipse.emf.ecore.impl.EStoreEObjectImpl;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.Resource.Internal;
+import org.eclipse.emf.ecore.util.DelegatingFeatureMap;
+import org.eclipse.emf.ecore.util.EcoreEList;
+import org.eclipse.emf.ecore.util.EcoreEMap;
+import org.eclipse.emf.ecore.util.FeatureMap;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+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.InternalCDOLoadable;
+import org.eclipse.emf.spi.cdo.InternalCDOObject;
+import org.eclipse.emf.spi.cdo.InternalCDOView;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * The base class of all <em>native</em> {@link CDOObject objects}.
+ *
+ * @author Eike Stepper
+ */
+public class CDOObjectImpl extends EStoreEObjectImpl implements InternalCDOObject
+{
+ private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_OBJECT, CDOObjectImpl.class);
+
+ private CDOID id;
+
+ private CDOState state;
+
+ private InternalCDOView view;
+
+ private InternalCDORevision revision;
+
+ /**
+ * CDO uses this list instead of eSettings for transient objects. EMF uses eSettings as cache. CDO deactivates the
+ * cache but EMF still used eSettings to store list wrappers. CDO needs another place to store the real list with the
+ * actual data (transient mode) and accessible through EStore. This allows CDO to always use the same instance of the
+ * list wrapper.
+ */
+ private transient Object[] cdoSettings;
+
+ public CDOObjectImpl()
+ {
+ state = CDOState.TRANSIENT;
+ eContainer = null;
+ cdoSettings = null;
+ }
+
+ public CDOID cdoID()
+ {
+ return id;
+ }
+
+ public CDOState cdoState()
+ {
+ return state;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public InternalCDORevision cdoRevision()
+ {
+ return revision;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public InternalCDOView cdoView()
+ {
+ return view;
+ }
+
+ public CDOResourceImpl cdoResource()
+ {
+ Resource resource = eResource();
+ if (resource instanceof CDOResourceImpl)
+ {
+ return (CDOResourceImpl)resource;
+ }
+
+ return null;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public CDOResourceImpl cdoDirectResource()
+ {
+ Resource.Internal resource = eDirectResource();
+ if (resource instanceof CDOResourceImpl)
+ {
+ return (CDOResourceImpl)resource;
+ }
+
+ return null;
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void cdoPrefetch(int depth)
+ {
+ view.prefetchRevisions(id, depth);
+ }
+
+ public void cdoReload()
+ {
+ CDOStateMachine.INSTANCE.reload(this);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public boolean cdoConflict()
+ {
+ return FSMUtil.isConflict(this);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public boolean cdoInvalid()
+ {
+ return FSMUtil.isInvalid(this);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public CDOLock cdoReadLock()
+ {
+ return createLock(this, LockType.READ);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public CDOLock cdoWriteLock()
+ {
+ return createLock(this, LockType.WRITE);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public CDOLock cdoWriteOption()
+ {
+ return createLock(this, LockType.OPTION);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public CDOLockState cdoLockState()
+ {
+ return getLockState(this);
+ }
+
+ public void cdoInternalSetID(CDOID id)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting ID: {0}", id); //$NON-NLS-1$
+ }
+
+ this.id = id;
+ }
+
+ public CDOState cdoInternalSetState(CDOState state)
+ {
+ CDOState oldState = this.state;
+ if (oldState != state)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting state {0} for {1}", state, this); //$NON-NLS-1$
+ }
+
+ this.state = state;
+ if (view != null)
+ {
+ view.handleObjectStateChanged(this, oldState, state);
+ }
+
+ return oldState;
+ }
+
+ return null;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void cdoInternalSetRevision(CDORevision revision)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting revision: {0}", revision); //$NON-NLS-1$
+ }
+
+ this.revision = (InternalCDORevision)revision;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void cdoInternalSetView(CDOView view)
+ {
+ this.view = (InternalCDOView)view;
+ if (this.view != null)
+ {
+ eSetStore(this.view.getStore());
+ }
+ else
+ {
+ eSetStore(null);
+ }
+ }
+
+ public void cdoInternalSetResource(CDOResource resource)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void cdoInternalPreLoad()
+ {
+ // Do nothing
+ }
+
+ public void cdoInternalPostLoad()
+ {
+ // Reset EMAP objects
+ if (eSettings != null)
+ {
+ // Make sure transient features are kept but persisted values are not cached.
+ EClass eClass = eClass();
+ for (int i = 0; i < eClass.getFeatureCount(); i++)
+ {
+ EStructuralFeature eFeature = cdoInternalDynamicFeature(i);
+
+ // We need to keep the existing list if possible.
+ if (EMFUtil.isPersistent(eFeature) && eSettings[i] instanceof InternalCDOLoadable)
+ {
+ ((InternalCDOLoadable)eSettings[i]).cdoInternalPostLoad();
+ }
+ }
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void cdoInternalPostInvalidate()
+ {
+ // Do nothing
+ }
+
+ public void cdoInternalPostAttach()
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Populating revision for {0}", this); //$NON-NLS-1$
+ }
+
+ revision.setContainerID(eContainer == null ? CDOID.NULL : view.convertObjectToID(eContainer, true));
+ revision.setContainingFeatureID(eContainerFeatureID);
+
+ Resource directResource = eDirectResource();
+ if (directResource instanceof CDOResource)
+ {
+ CDOResource cdoResource = (CDOResource)directResource;
+ revision.setResourceID(cdoResource.cdoID());
+ }
+
+ if (cdoSettings != null)
+ {
+ EClass eClass = eClass();
+ for (int i = 0; i < eClass.getFeatureCount(); i++)
+ {
+ EStructuralFeature eFeature = cdoInternalDynamicFeature(i);
+ if (EMFUtil.isPersistent(eFeature))
+ {
+ instanceToRevisionFeature(view, this, eFeature, cdoSettings[i]);
+ }
+ }
+
+ cdoSettings = null;
+ }
+ }
+
+ /**
+ * It is really important for accessing the data to go through {@link #cdoStore()}. {@link #eStore()} will redirect
+ * you to the transient data.
+ *
+ * @since 2.0
+ */
+ public void cdoInternalPostDetach(boolean remote)
+ {
+ if (remote)
+ {
+ // Do nothing
+ return;
+ }
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Depopulating revision for {0}", this); //$NON-NLS-1$
+ }
+
+ CDOStore store = cdoStore();
+ super.eSetDirectResource((Resource.Internal)store.getResource(this));
+ eContainer = store.getContainer(this);
+ eContainerFeatureID = store.getContainingFeatureID(this);
+
+ // Ensure that the internal eSettings array is initialized;
+ resetSettings();
+
+ EClass eClass = eClass();
+ for (int i = 0; i < eClass.getFeatureCount(); i++)
+ {
+ EStructuralFeature eFeature = cdoInternalDynamicFeature(i);
+ if (EMFUtil.isPersistent(eFeature))
+ {
+ revisionToInstanceFeature(this, revision, eFeature);
+ }
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void cdoInternalPostRollback()
+ {
+ // Do nothing
+ }
+
+ public void cdoInternalPreCommit()
+ {
+ // Do nothing
+ }
+
+ public InternalEObject cdoInternalInstance()
+ {
+ return this;
+ }
+
+ public EStructuralFeature cdoInternalDynamicFeature(int dynamicFeatureID)
+ {
+ return eDynamicFeature(dynamicFeatureID);
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ public synchronized EList<Adapter> eAdapters()
+ {
+ if (eAdapters == null)
+ {
+ // TODO Adjust for EObjectEAdapterList (see bug #247130)
+ eAdapters = new EAdapterList<Adapter>(this)
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void didAdd(int index, Adapter newObject)
+ {
+ if (view == null || view.isActive())
+ {
+ super.didAdd(index, newObject);
+ if (!FSMUtil.isTransient(CDOObjectImpl.this))
+ {
+ view.handleAddAdapter(CDOObjectImpl.this, newObject);
+ }
+ }
+ }
+
+ @Override
+ protected void didRemove(int index, Adapter oldObject)
+ {
+ if (view == null || view.isActive())
+ {
+ super.didRemove(index, oldObject);
+ if (!FSMUtil.isTransient(CDOObjectImpl.this))
+ {
+ view.handleRemoveAdapter(CDOObjectImpl.this, oldObject);
+ }
+ }
+ }
+ };
+ }
+
+ return eAdapters;
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ public Resource.Internal eDirectResource()
+ {
+ if (FSMUtil.isTransient(this))
+ {
+ return super.eDirectResource();
+ }
+
+ return (Resource.Internal)cdoStore().getResource(this);
+ }
+
+ @Override
+ public Resource.Internal eInternalResource()
+ {
+ if (FSMUtil.isInvalid(this))
+ {
+ return null;
+ }
+
+ return super.eInternalResource();
+ }
+
+ @Override
+ public Object dynamicGet(int dynamicFeatureID)
+ {
+ Object result = eSettings[dynamicFeatureID];
+ if (result == null)
+ {
+ EStructuralFeature eStructuralFeature = eDynamicFeature(dynamicFeatureID);
+ if (EMFUtil.isPersistent(eStructuralFeature))
+ {
+ if (FeatureMapUtil.isFeatureMap(eStructuralFeature))
+ {
+ eSettings[dynamicFeatureID] = result = createFeatureMap(eStructuralFeature);
+ }
+ else if (eStructuralFeature.isMany())
+ {
+ eSettings[dynamicFeatureID] = result = createList(eStructuralFeature);
+ }
+ else
+ {
+ result = eStore().get(this, eStructuralFeature, EStore.NO_INDEX);
+ if (eIsCaching())
+ {
+ eSettings[dynamicFeatureID] = result;
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public void dynamicSet(int dynamicFeatureID, Object value)
+ {
+ EStructuralFeature eStructuralFeature = eDynamicFeature(dynamicFeatureID);
+ if (!EMFUtil.isPersistent(eStructuralFeature))
+ {
+ eSettings[dynamicFeatureID] = value;
+ }
+ else
+ {
+ eStore().set(this, eStructuralFeature, EStore.NO_INDEX, value);
+ if (eIsCaching())
+ {
+ eSettings[dynamicFeatureID] = value;
+ }
+ }
+ }
+
+ @Override
+ public void dynamicUnset(int dynamicFeatureID)
+ {
+ EStructuralFeature eStructuralFeature = eDynamicFeature(dynamicFeatureID);
+ if (!EMFUtil.isPersistent(eStructuralFeature))
+ {
+ eSettings[dynamicFeatureID] = null;
+ }
+ else
+ {
+ eStore().unset(this, eDynamicFeature(dynamicFeatureID));
+ if (eIsCaching())
+ {
+ eSettings[dynamicFeatureID] = null;
+ }
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ protected boolean eDynamicIsSet(int dynamicFeatureID, EStructuralFeature eFeature)
+ {
+ if (dynamicFeatureID < 0)
+ {
+ return eOpenIsSet(eFeature);
+ }
+
+ if (EMFUtil.isPersistent(eFeature))
+ {
+ return eStore().isSet(this, eFeature);
+ }
+
+ return eSettingDelegate(eFeature).dynamicIsSet(this, eSettings(), dynamicFeatureID);
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ public EStore eStore()
+ {
+ if (FSMUtil.isTransient(this))
+ {
+ return CDOStoreSettingsImpl.INSTANCE;
+ }
+
+ return cdoStore();
+ }
+
+ @Override
+ public InternalEObject eInternalContainer()
+ {
+ InternalEObject container;
+ if (FSMUtil.isTransient(this))
+ {
+ container = eContainer;
+ }
+ else
+ {
+ // Delegate to CDOStore
+ container = cdoStore().getContainer(this);
+ }
+
+ return container;
+ }
+
+ @Override
+ public int eContainerFeatureID()
+ {
+ if (FSMUtil.isTransient(this))
+ {
+ return eContainerFeatureID;
+ }
+
+ // Delegate to CDOStore
+ return cdoStore().getContainingFeatureID(this);
+ }
+
+ /**
+ * Code took from {@link BasicEObjectImpl#eBasicSetContainer} and modify it to detect when object are moved in the
+ * same context. (E.g.: An object is moved from resA to resB. resA and resB belongs to the same CDORepositoryInfo.
+ * Without this special handling, a detach and newObject will be generated for the object moved)
+ *
+ * @since 2.0
+ */
+ @Override
+ public NotificationChain eBasicSetContainer(InternalEObject newContainer, int newContainerFeatureID,
+ NotificationChain msgs)
+ {
+ boolean isResourceRoot = this instanceof CDOResource && ((CDOResource)this).isRoot();
+
+ InternalEObject oldContainer = eInternalContainer();
+ Resource.Internal oldResource = eDirectResource();
+ Resource.Internal newResource = null;
+ if (oldResource != null)
+ {
+ if (newContainer != null && !eContainmentFeature(this, newContainer, newContainerFeatureID).isResolveProxies())
+ {
+ msgs = ((InternalEList<?>)oldResource.getContents()).basicRemove(this, msgs);
+ eSetDirectResource(null);
+ newResource = newContainer.eInternalResource();
+ }
+ else
+ {
+ oldResource = null;
+ }
+ }
+ else
+ {
+ if (oldContainer != null)
+ {
+ oldResource = oldContainer.eInternalResource();
+ }
+
+ if (newContainer != null)
+ {
+ newResource = newContainer.eInternalResource();
+ }
+ }
+
+ CDOView oldView = view;
+ CDOView newView = newResource != null && newResource instanceof CDOResource ? ((CDOResource)newResource).cdoView()
+ : null;
+
+ boolean moved = oldView != null && oldView == newView;
+ if (!moved && oldResource != null && !isResourceRoot)
+ {
+ oldResource.detached(this);
+ }
+
+ int oldContainerFeatureID = eContainerFeatureID();
+ eBasicSetContainer(newContainer, newContainerFeatureID);
+
+ if (!moved && oldResource != newResource && newResource != null)
+ {
+ newResource.attached(this);
+ }
+
+ if (eNotificationRequired())
+ {
+ if (oldContainer != null && oldContainerFeatureID >= 0 && oldContainerFeatureID != newContainerFeatureID)
+ {
+ ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, oldContainerFeatureID,
+ oldContainer, null);
+ if (msgs == null)
+ {
+ msgs = notification;
+ }
+ else
+ {
+ msgs.add(notification);
+ }
+ }
+
+ if (newContainerFeatureID >= 0)
+ {
+ ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, newContainerFeatureID,
+ oldContainerFeatureID == newContainerFeatureID ? oldContainer : null, newContainer);
+ if (msgs == null)
+ {
+ msgs = notification;
+ }
+ else
+ {
+ msgs.add(notification);
+ }
+ }
+ }
+
+ return msgs;
+ }
+
+ /**
+ * Code took from {@link BasicEObjectImpl#eSetResource} and modify it to detect when object are moved in the same
+ * context.
+ *
+ * @since 2.0
+ */
+ @Override
+ public NotificationChain eSetResource(Resource.Internal resource, NotificationChain notifications)
+ {
+ Resource.Internal oldResource = eDirectResource();
+
+ CDOView oldView = view;
+ CDOView newView = resource != null && resource instanceof CDOResource ? ((CDOResource)resource).cdoView() : null;
+
+ boolean isSameView;
+ if (state == CDOState.NEW)
+ {
+ isSameView = false;
+ }
+ else
+ {
+ isSameView = oldView != null && oldView == newView;
+ }
+
+ if (oldResource != null)
+ {
+ notifications = ((InternalEList<?>)oldResource.getContents()).basicRemove(this, notifications);
+
+ // When setting the resource to null we assume that detach has already been called in the resource implementation
+ if (!isSameView && resource != null)
+ {
+ oldResource.detached(this);
+ }
+ }
+
+ InternalEObject oldContainer = eInternalContainer();
+ if (oldContainer != null && !isSameView)
+ {
+ if (eContainmentFeature().isResolveProxies())
+ {
+ Resource.Internal oldContainerResource = oldContainer.eInternalResource();
+ if (oldContainerResource != null)
+ {
+ // If we're not setting a new resource, attach it to the old container's resource.
+ if (resource == null)
+ {
+ oldContainerResource.attached(this);
+ }
+
+ // If we didn't detach it from an old resource already, detach it from the old container's resource.
+ //
+ else if (oldResource == null)
+ {
+ oldContainerResource.detached(this);
+ }
+ }
+ }
+ else
+ {
+ notifications = eBasicRemoveFromContainer(notifications);
+ notifications = eBasicSetContainer(null, -1, notifications);
+ }
+ }
+
+ eSetDirectResource(resource);
+
+ return notifications;
+ }
+
+ /**
+ * Specializing the behaviour of {@link #hashCode()} is not permitted as per {@link EObject} specification.
+ */
+ @Override
+ public final int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /**
+ * Specializing the behaviour of {@link #equals(Object)} is not permitted as per {@link EObject} specification.
+ */
+ @Override
+ public final boolean equals(Object obj)
+ {
+ return super.equals(obj);
+ }
+
+ @Override
+ public String toString()
+ {
+ if (id == null)
+ {
+ return eClass().getName() + "?"; //$NON-NLS-1$
+ }
+
+ return eClass().getName() + "@" + id; //$NON-NLS-1$
+ }
+
+ /**
+ * @since 2.0
+ */
+ protected Object[] cdoSettings()
+ {
+ if (cdoSettings == null)
+ {
+ int size = eClass().getFeatureCount() - eStaticFeatureCount();
+ if (size == 0)
+ {
+ cdoSettings = ENO_SETTINGS;
+ }
+ else
+ {
+ cdoSettings = new Object[size];
+ }
+ }
+
+ return cdoSettings;
+ }
+
+ /**
+ * @since 2.0
+ */
+ protected Object[] cdoBasicSettings()
+ {
+ return cdoSettings;
+ }
+
+ @Override
+ protected FeatureMap createFeatureMap(EStructuralFeature eStructuralFeature)
+ {
+ return new CDOStoreFeatureMap(eStructuralFeature);
+ }
+
+ /**
+ * @since 4.1
+ */
+ protected CDOStoreEcoreEMap createMap(EStructuralFeature eStructuralFeature)
+ {
+ return new CDOStoreEcoreEMap(eStructuralFeature);
+ }
+
+ /**
+ * @since 4.1
+ */
+ protected CDOStoreUnorderedEList<Object> createUnorderedList(EStructuralFeature eStructuralFeature)
+ {
+ return new CDOStoreUnorderedEList<Object>(eStructuralFeature);
+ }
+
+ @Override
+ protected EList<?> createList(EStructuralFeature eStructuralFeature)
+ {
+ if (isMap(eStructuralFeature))
+ {
+ return createMap(eStructuralFeature);
+ }
+
+ if (!eStructuralFeature.isOrdered())
+ {
+ return createUnorderedList(eStructuralFeature);
+ }
+
+ return super.createList(eStructuralFeature);
+ }
+
+ private boolean isMap(EStructuralFeature eStructuralFeature)
+ {
+ // Answer from Christian Damus:
+ // Java ensures that string constants are interned, so this is actually
+ // more efficient than .equals() and it's correct
+ return eStructuralFeature.getEType().getInstanceClassName() == "java.util.Map$Entry"; //$NON-NLS-1$
+ }
+
+ @Override
+ protected void eInitializeContainer()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void eSetDirectResource(Internal resource)
+ {
+ if (FSMUtil.isTransient(this))
+ {
+ super.eSetDirectResource(resource);
+ }
+ else if (resource instanceof CDOResourceImpl || resource == null)
+ {
+ cdoStore().setContainer(this, (CDOResourceImpl)resource, eInternalContainer(), eContainerFeatureID());
+ }
+ else
+ {
+ throw new IllegalArgumentException(Messages.getString("CDOObjectImpl.8")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Don't cache non-transient features in this CDOObject's {@link #eSettings()}.
+ */
+ @Override
+ protected boolean eIsCaching()
+ {
+ return false;
+ }
+
+ @Override
+ protected void eBasicSetContainer(InternalEObject newEContainer, int newContainerFeatureID)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Setting container: {0}, featureID={1}", newEContainer, newContainerFeatureID); //$NON-NLS-1$
+ }
+
+ if (FSMUtil.isTransient(this))
+ {
+ super.eBasicSetContainer(newEContainer, newContainerFeatureID);
+ }
+ else
+ {
+ cdoStore().setContainer(this, cdoDirectResource(), newEContainer, newContainerFeatureID);
+ }
+ }
+
+ private CDOStore cdoStore()
+ {
+ return view.getStore();
+ }
+
+ private void resetSettings()
+ {
+ cdoSettings = null;
+ cdoSettings();
+ }
+
+ /**
+ * Adjust the reference ONLY if the opposite reference used CDOID. This is true ONLY if the state of <cdo>this</code>
+ * was not {@link CDOState#NEW}.
+ */
+ private static void adjustOppositeReference(InternalCDOObject instance, InternalEObject object, EReference feature)
+ {
+ if (object != null)
+ {
+ InternalCDOObject cdoObject = (InternalCDOObject)CDOUtil.getCDOObject(object);
+ if (cdoObject != null && !FSMUtil.isTransient(cdoObject))
+ {
+ if (feature.isMany())
+ {
+ int index = cdoObject.eStore().indexOf(cdoObject, feature, instance.cdoID());
+
+ // TODO Simon Log an error in the new view.getErrors() in the case we are not able to find the object.
+ // Cannot throw an exception, the detach process is too far.
+ if (index != -1)
+ {
+ cdoObject.eStore().set(cdoObject, feature, index, instance);
+ }
+ }
+ else
+ {
+ cdoObject.eStore().set(cdoObject, feature, 0, instance);
+ }
+ }
+ else
+ {
+ if (feature.isResolveProxies())
+ {
+ // We should not trigger events. But we have no choice :-(.
+ if (feature.isMany())
+ {
+ @SuppressWarnings("unchecked")
+ InternalEList<Object> list = (InternalEList<Object>)object.eGet(feature);
+ int index = list.indexOf(instance);
+ if (index != -1)
+ {
+ list.set(index, instance);
+ }
+ }
+ else
+ {
+ object.eSet(feature, instance);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public static void revisionToInstanceFeature(InternalCDOObject instance, InternalCDORevision revision,
+ EStructuralFeature eFeature)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Depopulating feature {0}", eFeature); //$NON-NLS-1$
+ }
+
+ EStructuralFeature.Internal internalFeature = (EStructuralFeature.Internal)eFeature;
+ InternalCDOView view = instance.cdoView();
+ EReference oppositeReference = view.isObjectNew(instance.cdoID()) ? null : internalFeature.getEOpposite();
+
+ CDOStore cdoStore = view.getStore();
+ EStore eStore = instance.eStore();
+
+ if (eFeature.isMany())
+ {
+ int size = cdoStore.size(instance, eFeature);
+ for (int index = 0; index < size; index++)
+ {
+ // Do not trigger events
+ // Do not trigger inverse updates
+ Object object = cdoStore.get(instance, eFeature, index);
+ eStore.add(instance, eFeature, index, object);
+ if (oppositeReference != null)
+ {
+ adjustOppositeReference(instance, (InternalEObject)object, oppositeReference);
+ }
+ }
+ }
+ else
+ {
+ Object object = cdoStore.get(instance, eFeature, EStore.NO_INDEX);
+ eStore.set(instance, eFeature, EStore.NO_INDEX, object);
+ if (oppositeReference != null)
+ {
+ adjustOppositeReference(instance, (InternalEObject)object, oppositeReference);
+ }
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ public static void instanceToRevisionFeature(InternalCDOView view, InternalCDOObject object,
+ EStructuralFeature feature, Object setting)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.format("Populating feature {0}", feature); //$NON-NLS-1$
+ }
+
+ CDOStore cdoStore = view.getStore();
+ InternalCDORevision revision = object.cdoRevision();
+
+ if (feature.isMany())
+ {
+ if (setting != null)
+ {
+ int index = 0;
+ @SuppressWarnings("unchecked")
+ EList<Object> list = (EList<Object>)setting;
+ for (Object value : list)
+ {
+ value = cdoStore.convertToCDO(object, feature, value);
+ revision.add(feature, index++, value);
+ }
+ }
+ }
+ else
+ {
+ setting = cdoStore.convertToCDO(object, feature, setting);
+ revision.set(feature, 0, setting);
+ }
+ }
+
+ /**
+ * @since 4.1
+ */
+ public static CDOLock createLock(InternalCDOObject object, LockType type)
+ {
+ if (FSMUtil.isTransient(object))
+ {
+ throw new IllegalStateException("Call CDOView.lockObjects() for transient object " + object);
+ }
+
+ return new CDOLockImpl(object, type);
+ }
+
+ /**
+ * @since 4.1
+ */
+ public static CDOLockState getLockState(InternalCDOObject object)
+ {
+ if (!FSMUtil.isTransient(object))
+ {
+ InternalCDOView view = object.cdoView();
+ CDOID id = object.cdoID();
+
+ return view.getLockStates(Collections.singletonList(id))[0];
+ }
+
+ return null;
+ }
+
+ /**
+ * For internal use only.
+ *
+ * @author Simon McDuff
+ * @since 2.0
+ */
+ public static class CDOStoreSettingsImpl implements InternalEObject.EStore
+ {
+ public static CDOStoreSettingsImpl INSTANCE = new CDOStoreSettingsImpl();
+
+ private CDOStoreSettingsImpl()
+ {
+ }
+
+ protected Object getValue(InternalEObject eObject, int dynamicFeatureID)
+ {
+ Object value = ((CDOObjectImpl)eObject).cdoSettings()[dynamicFeatureID];
+ return value;
+ }
+
+ protected EList<Object> getValueAsList(InternalEObject eObject, int dynamicFeatureID)
+ {
+ @SuppressWarnings("unchecked")
+ EList<Object> result = (EList<Object>)getValue(eObject, dynamicFeatureID);
+ if (result == null)
+ {
+ result = new BasicEList<Object>();
+ ((CDOObjectImpl)eObject).cdoSettings()[dynamicFeatureID] = result;
+ }
+
+ return result;
+ }
+
+ protected Object setValue(InternalEObject eObject, int dynamicFeatureID, Object newValue)
+ {
+ Object settings[] = ((CDOObjectImpl)eObject).cdoSettings();
+ Object oldSetting = settings[dynamicFeatureID];
+ settings[dynamicFeatureID] = newValue;
+ return oldSetting;
+ }
+
+ protected int eDynamicFeatureID(InternalEObject eObject, EStructuralFeature feature)
+ {
+ return ((CDOObjectImpl)eObject).eDynamicFeatureID(feature);
+ }
+
+ public Object get(InternalEObject eObject, EStructuralFeature feature, int index)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ if (index != NO_INDEX)
+ {
+ return getValueAsList(eObject, dynamicFeatureID).get(index);
+ }
+
+ return getValue(eObject, dynamicFeatureID);
+ }
+
+ public Object set(InternalEObject eObject, EStructuralFeature feature, int index, Object value)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ if (index != NO_INDEX)
+ {
+ return getValueAsList(eObject, dynamicFeatureID).set(index, value);
+ }
+
+ return setValue(eObject, dynamicFeatureID, value);
+ }
+
+ public void add(InternalEObject eObject, EStructuralFeature feature, int index, Object value)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ getValueAsList(eObject, dynamicFeatureID).add(index, value);
+ }
+
+ public Object remove(InternalEObject eObject, EStructuralFeature feature, int index)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ return getValueAsList(eObject, dynamicFeatureID).remove(index);
+ }
+
+ public Object move(InternalEObject eObject, EStructuralFeature feature, int targetIndex, int sourceIndex)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ return getValueAsList(eObject, dynamicFeatureID).move(targetIndex, sourceIndex);
+ }
+
+ public void clear(InternalEObject eObject, EStructuralFeature feature)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ if (feature.isMany())
+ {
+ getValueAsList(eObject, dynamicFeatureID).clear();
+ }
+
+ setValue(eObject, dynamicFeatureID, null);
+ }
+
+ public int size(InternalEObject eObject, EStructuralFeature feature)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ return getValueAsList(eObject, dynamicFeatureID).size();
+ }
+
+ public int indexOf(InternalEObject eObject, EStructuralFeature feature, Object value)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ return getValueAsList(eObject, dynamicFeatureID).indexOf(value);
+ }
+
+ public int lastIndexOf(InternalEObject eObject, EStructuralFeature feature, Object value)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ return getValueAsList(eObject, dynamicFeatureID).lastIndexOf(value);
+ }
+
+ public Object[] toArray(InternalEObject eObject, EStructuralFeature feature)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ return getValueAsList(eObject, dynamicFeatureID).toArray();
+ }
+
+ public <T> T[] toArray(InternalEObject eObject, EStructuralFeature feature, T[] array)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ return getValueAsList(eObject, dynamicFeatureID).toArray(array);
+ }
+
+ public boolean isEmpty(InternalEObject eObject, EStructuralFeature feature)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ return getValueAsList(eObject, dynamicFeatureID).isEmpty();
+ }
+
+ public boolean contains(InternalEObject eObject, EStructuralFeature feature, Object value)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ return getValueAsList(eObject, dynamicFeatureID).contains(value);
+ }
+
+ public int hashCode(InternalEObject eObject, EStructuralFeature feature)
+ {
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ return getValueAsList(eObject, dynamicFeatureID).hashCode();
+ }
+
+ public InternalEObject getContainer(InternalEObject eObject)
+ {
+ return null;
+ }
+
+ public EStructuralFeature getContainingFeature(InternalEObject eObject)
+ {
+ throw new UnsupportedOperationException("Should never be called");
+ }
+
+ public EObject create(EClass eClass)
+ {
+ return new EStoreEObjectImpl(eClass, this);
+ }
+
+ public boolean isSet(InternalEObject eObject, EStructuralFeature feature)
+ {
+ if (!feature.isUnsettable())
+ {
+ if (feature.isMany())
+ {
+ @SuppressWarnings("unchecked")
+ InternalEList<Object> list = (InternalEList<Object>)eObject.eGet(feature);
+ return list != null && !list.isEmpty();
+ }
+
+ return !ObjectUtil.equals(eObject.eGet(feature), feature.getDefaultValue());
+ }
+
+ Object[] settings = ((CDOObjectImpl)eObject).cdoBasicSettings();
+ if (settings == null)
+ {
+ return false;
+ }
+
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ return settings[dynamicFeatureID] != null;
+ }
+
+ public void unset(InternalEObject eObject, EStructuralFeature feature)
+ {
+ Object[] settings = ((CDOObjectImpl)eObject).cdoBasicSettings();
+ if (settings == null)
+ {
+ // Is already unset
+ return;
+ }
+
+ int dynamicFeatureID = eDynamicFeatureID(eObject, feature);
+ if (feature.isUnsettable())
+ {
+ settings[dynamicFeatureID] = null;
+ }
+ else
+ {
+ settings[dynamicFeatureID] = feature.getDefaultValue();
+ }
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ * @since 4.1
+ */
+ public class CDOStoreEcoreEMap extends EcoreEMap<Object, Object> implements InternalCDOLoadable
+ {
+ private static final long serialVersionUID = 1L;
+
+ public CDOStoreEcoreEMap(EStructuralFeature eStructuralFeature)
+ {
+ super((EClass)eStructuralFeature.getEType(), BasicEMap.Entry.class, null);
+ delegateEList = new BasicEStoreEList<BasicEMap.Entry<Object, Object>>(CDOObjectImpl.this, eStructuralFeature)
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void unset()
+ {
+ super.unset();
+ doClear();
+ }
+
+ @Override
+ protected void didAdd(int index, BasicEMap.Entry<Object, Object> newObject)
+ {
+ CDOStoreEcoreEMap.this.doPut(newObject);
+ }
+
+ @Override
+ protected void didSet(int index, BasicEMap.Entry<Object, Object> newObject,
+ BasicEMap.Entry<Object, Object> oldObject)
+ {
+ didRemove(index, oldObject);
+ didAdd(index, newObject);
+ }
+
+ @Override
+ protected void didRemove(int index, BasicEMap.Entry<Object, Object> oldObject)
+ {
+ CDOStoreEcoreEMap.this.doRemove(oldObject);
+ }
+
+ @Override
+ protected void didClear(int size, Object[] oldObjects)
+ {
+ CDOStoreEcoreEMap.this.doClear();
+ }
+
+ @Override
+ protected void didMove(int index, BasicEMap.Entry<Object, Object> movedObject, int oldIndex)
+ {
+ CDOStoreEcoreEMap.this.doMove(movedObject);
+ }
+ };
+
+ size = delegateEList.size();
+ }
+
+ private void checkListForReading()
+ {
+ if (!FSMUtil.isTransient(CDOObjectImpl.this))
+ {
+ CDOStateMachine.INSTANCE.read(CDOObjectImpl.this);
+ }
+ }
+
+ /**
+ * Ensures that the entry data is created and is populated with contents of the delegate list.
+ */
+ @Override
+ protected synchronized void ensureEntryDataExists()
+ {
+ checkListForReading();
+ super.ensureEntryDataExists();
+ }
+
+ @Override
+ public int size()
+ {
+ checkListForReading();
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ checkListForReading();
+ return size == 0;
+ }
+
+ @Override
+ public boolean contains(Object object)
+ {
+ checkListForReading();
+ return super.contains(object);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> collection)
+ {
+ checkListForReading();
+ return super.containsAll(collection);
+ }
+
+ @Override
+ public boolean containsKey(Object key)
+ {
+ checkListForReading();
+ return super.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value)
+ {
+ checkListForReading();
+ return super.containsValue(value);
+ }
+
+ public void cdoInternalPostLoad()
+ {
+ entryData = null;
+ size = delegateEList.size();
+ }
+
+ public void cdoInternalPreLoad()
+ {
+ }
+ }
+
+ /**
+ * @author Andras Peteri
+ * @since 4.1
+ */
+ public class CDOStoreUnorderedEList<E> extends BasicEStoreEList<E>
+ {
+ private static final long serialVersionUID = 1L;
+
+ public CDOStoreUnorderedEList(EStructuralFeature feature)
+ {
+ super(CDOObjectImpl.this, feature);
+ }
+
+ @Override
+ public E remove(int index)
+ {
+ boolean oldObjectIsLast = index == size() - 1;
+ E oldObject = super.remove(index);
+
+ if (!oldObjectIsLast)
+ {
+ move(index, size() - 1);
+ }
+
+ return oldObject;
+ }
+ }
+
+ /**
+ * TODO Remove this when EMF has fixed bug 197487
+ *
+ * @author Eike Stepper
+ */
+ public class CDOStoreFeatureMap extends DelegatingFeatureMap
+ {
+ private static final long serialVersionUID = 1L;
+
+ public CDOStoreFeatureMap(EStructuralFeature eStructuralFeature)
+ {
+ super(CDOObjectImpl.this, eStructuralFeature);
+ }
+
+ @Override
+ protected List<FeatureMap.Entry> delegateList()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public EStructuralFeature getEStructuralFeature()
+ {
+ return eStructuralFeature;
+ }
+
+ @Override
+ protected void delegateAdd(int index, Entry object)
+ {
+ eStore().add(owner, eStructuralFeature, index, object);
+ }
+
+ @Override
+ protected void delegateAdd(Entry object)
+ {
+ delegateAdd(delegateSize(), object);
+ }
+
+ @Override
+ protected List<FeatureMap.Entry> delegateBasicList()
+ {
+ int size = delegateSize();
+ if (size == 0)
+ {
+ return ECollections.emptyEList();
+ }
+
+ Object[] data = cdoStore().toArray(owner, eStructuralFeature);
+ return new EcoreEList.UnmodifiableEList<FeatureMap.Entry>(owner, eStructuralFeature, data.length, data);
+ }
+
+ @Override
+ protected void delegateClear()
+ {
+ eStore().clear(owner, eStructuralFeature);
+ }
+
+ @Override
+ protected boolean delegateContains(Object object)
+ {
+ return eStore().contains(owner, eStructuralFeature, object);
+ }
+
+ @Override
+ protected boolean delegateContainsAll(Collection<?> collection)
+ {
+ for (Object o : collection)
+ {
+ if (!delegateContains(o))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ protected Entry delegateGet(int index)
+ {
+ return (Entry)eStore().get(owner, eStructuralFeature, index);
+ }
+
+ @Override
+ protected int delegateHashCode()
+ {
+ return eStore().hashCode(owner, eStructuralFeature);
+ }
+
+ @Override
+ protected int delegateIndexOf(Object object)
+ {
+ return eStore().indexOf(owner, eStructuralFeature, object);
+ }
+
+ @Override
+ protected boolean delegateIsEmpty()
+ {
+ return eStore().isEmpty(owner, eStructuralFeature);
+ }
+
+ @Override
+ protected Iterator<FeatureMap.Entry> delegateIterator()
+ {
+ return iterator();
+ }
+
+ @Override
+ protected int delegateLastIndexOf(Object object)
+ {
+ return eStore().lastIndexOf(owner, eStructuralFeature, object);
+ }
+
+ @Override
+ protected ListIterator<FeatureMap.Entry> delegateListIterator()
+ {
+ return listIterator();
+ }
+
+ @Override
+ protected Entry delegateRemove(int index)
+ {
+ return (Entry)eStore().remove(owner, eStructuralFeature, index);
+ }
+
+ @Override
+ protected Entry delegateSet(int index, Entry object)
+ {
+ return (Entry)eStore().set(owner, eStructuralFeature, index, object);
+ }
+
+ @Override
+ protected int delegateSize()
+ {
+ return eStore().size(owner, eStructuralFeature);
+ }
+
+ @Override
+ protected Object[] delegateToArray()
+ {
+ return eStore().toArray(owner, eStructuralFeature);
+ }
+
+ @Override
+ protected <T> T[] delegateToArray(T[] array)
+ {
+ return eStore().toArray(owner, eStructuralFeature, array);
+ }
+
+ @Override
+ protected Entry delegateMove(int targetIndex, int sourceIndex)
+ {
+ return (Entry)eStore().move(owner, eStructuralFeature, targetIndex, sourceIndex);
+ }
+
+ @Override
+ protected String delegateToString()
+ {
+ StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append("["); //$NON-NLS-1$
+ for (int i = 0, size = size(); i < size;)
+ {
+ Object value = delegateGet(i);
+ stringBuffer.append(String.valueOf(value));
+ if (++i < size)
+ {
+ stringBuffer.append(", "); //$NON-NLS-1$
+ }
+ }
+
+ stringBuffer.append("]"); //$NON-NLS-1$
+ return stringBuffer.toString();
+ }
+ }
+}
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 36e51ebf6a..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 @@ -331,8 +331,6 @@ public abstract class CDOLegacyWrapper extends CDOObjectWrapper { instanceToRevisionFeature(feature, packageRegistry); } - - revision.setUnchunked(); } protected void instanceToRevisionContainment() diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java index 708f06e23f..f8541bf747 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java @@ -1,1859 +1,1849 @@ -/* - * 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 226778 - * Simon McDuff - bug 230832 - * Simon McDuff - bug 233490 - * Simon McDuff - bug 213402 - * Victor Roldan Betancort - maintenance - */ -package org.eclipse.emf.internal.cdo.session; - -import org.eclipse.emf.cdo.common.CDOCommonRepository; -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.CDOChangeKind; -import org.eclipse.emf.cdo.common.commit.CDOChangeSetData; -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.CDOIDGenerator; -import org.eclipse.emf.cdo.common.lob.CDOLobInfo; -import org.eclipse.emf.cdo.common.lob.CDOLobStore; -import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; -import org.eclipse.emf.cdo.common.model.CDOPackageUnit; -import org.eclipse.emf.cdo.common.model.EMFUtil; -import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator; -import org.eclipse.emf.cdo.common.revision.CDOElementProxy; -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.CDOAddFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta; -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.CDOListFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta; -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.CDOException; -import org.eclipse.emf.cdo.common.util.RepositoryStateChangedEvent; -import org.eclipse.emf.cdo.common.util.RepositoryTypeChangedEvent; -import org.eclipse.emf.cdo.eresource.EresourcePackage; -import org.eclipse.emf.cdo.etypes.EtypesPackage; -import org.eclipse.emf.cdo.internal.common.revision.delta.CDOMoveFeatureDeltaImpl; -import org.eclipse.emf.cdo.internal.common.revision.delta.CDOSetFeatureDeltaImpl; -import org.eclipse.emf.cdo.internal.common.revision.delta.CDOSingleValueFeatureDeltaImpl; -import org.eclipse.emf.cdo.session.CDOCollectionLoadingPolicy; -import org.eclipse.emf.cdo.session.CDORepositoryInfo; -import org.eclipse.emf.cdo.session.CDOSession; -import org.eclipse.emf.cdo.session.CDOSessionInvalidationEvent; -import org.eclipse.emf.cdo.session.CDOSessionLocksChangedEvent; -import org.eclipse.emf.cdo.session.remote.CDORemoteSessionManager; -import org.eclipse.emf.cdo.spi.common.CDOLobStoreImpl; -import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; -import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch; -import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager; -import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo; -import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager; -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.DetachedCDORevision; -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.InternalCDORevisionDelta; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; -import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision; -import org.eclipse.emf.cdo.transaction.CDOTransaction; -import org.eclipse.emf.cdo.util.CDOUtil; -import org.eclipse.emf.cdo.view.CDOFetchRuleManager; -import org.eclipse.emf.cdo.view.CDOView; - -import org.eclipse.emf.internal.cdo.analyzer.NOOPFetchRuleManager; -import org.eclipse.emf.internal.cdo.bundle.OM; -import org.eclipse.emf.internal.cdo.messages.Messages; -import org.eclipse.emf.internal.cdo.object.CDOFactoryImpl; -import org.eclipse.emf.internal.cdo.session.remote.CDORemoteSessionManagerImpl; -import org.eclipse.emf.internal.cdo.util.DefaultLocksChangedEvent; - -import org.eclipse.net4j.util.ObjectUtil; -import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; -import org.eclipse.net4j.util.WrappedException; -import org.eclipse.net4j.util.collection.Pair; -import org.eclipse.net4j.util.concurrent.IRWLockManager; -import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; -import org.eclipse.net4j.util.concurrent.IRWOLockManager; -import org.eclipse.net4j.util.concurrent.QueueRunner; -import org.eclipse.net4j.util.concurrent.RWOLockManager; -import org.eclipse.net4j.util.event.Event; -import org.eclipse.net4j.util.event.EventUtil; -import org.eclipse.net4j.util.event.IEvent; -import org.eclipse.net4j.util.event.IListener; -import org.eclipse.net4j.util.event.Notifier; -import org.eclipse.net4j.util.io.IOUtil; -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.net4j.util.options.OptionsEvent; - -import org.eclipse.emf.common.util.ECollections; -import org.eclipse.emf.ecore.EPackage; -import org.eclipse.emf.ecore.EReference; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.EcorePackage; -import org.eclipse.emf.spi.cdo.CDOSessionProtocol; -import org.eclipse.emf.spi.cdo.CDOSessionProtocol.RefreshSessionResult; -import org.eclipse.emf.spi.cdo.InternalCDORemoteSessionManager; -import org.eclipse.emf.spi.cdo.InternalCDOSession; -import org.eclipse.emf.spi.cdo.InternalCDOTransaction; -import org.eclipse.emf.spi.cdo.InternalCDOView; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * @author Eike Stepper - */ -public abstract class CDOSessionImpl extends CDOTransactionContainerImpl implements InternalCDOSession -{ - private ExceptionHandler exceptionHandler; - - private CDOIDGenerator idGenerator; - - private InternalCDOPackageRegistry packageRegistry; - - private InternalCDOBranchManager branchManager; - - private InternalCDORevisionManager revisionManager; - - private InternalCDOCommitInfoManager commitInfoManager; - - private CDOSessionProtocol sessionProtocol; - - @ExcludeFromDump - private IListener sessionProtocolListener = new LifecycleEventAdapter() - { - @Override - protected void onDeactivated(ILifecycle lifecycle) - { - sessionProtocolDeactivated(); - } - }; - - private int sessionID; - - private String userID; - - private long lastUpdateTime; - - @ExcludeFromDump - private LastUpdateTimeLock lastUpdateTimeLock = new LastUpdateTimeLock(); - - private CDOSession.Options options = createOptions(); - - private OutOfSequenceInvalidations outOfSequenceInvalidations = new OutOfSequenceInvalidations(); - - private QueueRunner invalidationRunner; - - private CDORepositoryInfo repositoryInfo; - - private CDOFetchRuleManager fetchRuleManager; - - private IRWOLockManager<CDOSessionImpl, Object> lockManager = new RWOLockManager<CDOSessionImpl, Object>(); - - @ExcludeFromDump - private Set<CDOSessionImpl> singletonCollection = Collections.singleton(this); - - private boolean mainBranchLocal; - - private CDOAuthenticator authenticator; - - private InternalCDORemoteSessionManager remoteSessionManager; - - /** - * A map to track for every object that was committed since this session's last refresh, onto what CDOBranchPoint it - * was committed. (Used only for sticky transactions, see bug 290032 - Sticky views.) - */ - private Map<CDOID, CDOBranchPoint> committedSinceLastRefresh = new HashMap<CDOID, CDOBranchPoint>(); - - static - { - // Ensure that these 3 packages are registered with the global package registry in stand-alone - EcorePackage.eINSTANCE.getClass(); - EresourcePackage.eINSTANCE.getClass(); - EtypesPackage.eINSTANCE.getClass(); - } - - public CDOSessionImpl() - { - } - - public CDORepositoryInfo getRepositoryInfo() - { - return repositoryInfo; - } - - public void setRepositoryInfo(CDORepositoryInfo repositoryInfo) - { - this.repositoryInfo = repositoryInfo; - } - - public int getSessionID() - { - return sessionID; - } - - public void setSessionID(int sessionID) - { - this.sessionID = sessionID; - } - - public String getUserID() - { - return userID; - } - - public void setUserID(String userID) - { - this.userID = userID; - } - - public ExceptionHandler getExceptionHandler() - { - return exceptionHandler; - } - - public void setExceptionHandler(ExceptionHandler exceptionHandler) - { - checkInactive(); - this.exceptionHandler = exceptionHandler; - } - - public CDOIDGenerator getIDGenerator() - { - return idGenerator; - } - - public void setIDGenerator(CDOIDGenerator idGenerator) - { - checkInactive(); - this.idGenerator = idGenerator; - } - - public InternalCDOPackageRegistry getPackageRegistry() - { - return packageRegistry; - } - - public void setPackageRegistry(InternalCDOPackageRegistry packageRegistry) - { - this.packageRegistry = packageRegistry; - } - - public InternalCDOBranchManager getBranchManager() - { - return branchManager; - } - - public void setBranchManager(InternalCDOBranchManager branchManager) - { - checkInactive(); - this.branchManager = branchManager; - } - - public InternalCDORevisionManager getRevisionManager() - { - return revisionManager; - } - - public void setRevisionManager(InternalCDORevisionManager revisionManager) - { - checkInactive(); - this.revisionManager = revisionManager; - } - - public InternalCDOCommitInfoManager getCommitInfoManager() - { - return commitInfoManager; - } - - public void setCommitInfoManager(InternalCDOCommitInfoManager commitInfoManager) - { - checkInactive(); - this.commitInfoManager = commitInfoManager; - } - - public CDOSessionProtocol getSessionProtocol() - { - return sessionProtocol; - } - - public void setSessionProtocol(CDOSessionProtocol sessionProtocol) - { - checkInactive(); - if (exceptionHandler == null) - { - this.sessionProtocol = sessionProtocol; - } - else - { - if (this.sessionProtocol instanceof DelegatingSessionProtocol) - { - ((DelegatingSessionProtocol)this.sessionProtocol).setDelegate(sessionProtocol); - } - else - { - this.sessionProtocol = new DelegatingSessionProtocol(sessionProtocol, exceptionHandler); - } - } - } - - /** - * @since 3.0 - */ - public CDOFetchRuleManager getFetchRuleManager() - { - return fetchRuleManager; - } - - /** - * @since 3.0 - */ - public void setFetchRuleManager(CDOFetchRuleManager fetchRuleManager) - { - if (fetchRuleManager == null) - { - fetchRuleManager = new NOOPFetchRuleManager() - { - public CDOCollectionLoadingPolicy getCollectionLoadingPolicy() - { - return options().getCollectionLoadingPolicy(); - } - }; - } - - this.fetchRuleManager = fetchRuleManager; - } - - public CDOAuthenticator getAuthenticator() - { - return authenticator; - } - - public void setAuthenticator(CDOAuthenticator authenticator) - { - this.authenticator = authenticator; - } - - public boolean isMainBranchLocal() - { - return mainBranchLocal; - } - - public void setMainBranchLocal(boolean mainBranchLocal) - { - this.mainBranchLocal = mainBranchLocal; - } - - public InternalCDORemoteSessionManager getRemoteSessionManager() - { - return remoteSessionManager; - } - - public void setRemoteSessionManager(InternalCDORemoteSessionManager remoteSessionManager) - { - this.remoteSessionManager = remoteSessionManager; - } - - public CDOLobStore getLobStore() - { - final CDOLobStore cache = options().getLobCache(); - return new CDOLobStore.Delegating() - { - @Override - public InputStream getBinary(final CDOLobInfo info) throws IOException - { - for (;;) - { - try - { - return super.getBinary(info); - } - catch (FileNotFoundException couldNotBeRead) - { - try - { - loadBinary(info); - } - catch (FileNotFoundException couldNotBeCreated) - { - // Try to read again - } - } - } - } - - @Override - public Reader getCharacter(CDOLobInfo info) throws IOException - { - for (;;) - { - try - { - return super.getCharacter(info); - } - catch (FileNotFoundException couldNotBeRead) - { - try - { - loadCharacter(info); - } - catch (FileNotFoundException couldNotBeCreated) - { - // Try to read again - } - } - } - } - - private void loadBinary(final CDOLobInfo info) throws IOException - { - final File file = getDelegate().getBinaryFile(info.getID()); - final FileOutputStream out = new FileOutputStream(file); - - loadLobAsync(info, new Runnable() - { - public void run() - { - try - { - getSessionProtocol().loadLob(info, out); - } - catch (Throwable t) - { - OM.LOG.error(t); - IOUtil.delete(file); - } - } - }); - } - - private void loadCharacter(final CDOLobInfo info) throws IOException - { - final File file = getDelegate().getCharacterFile(info.getID()); - final FileWriter out = new FileWriter(file); - - loadLobAsync(info, new Runnable() - { - public void run() - { - try - { - getSessionProtocol().loadLob(info, out); - } - catch (Throwable t) - { - OM.LOG.error(t); - IOUtil.delete(file); - } - } - }); - } - - @Override - protected CDOLobStore getDelegate() - { - return cache; - } - }; - } - - protected void loadLobAsync(CDOLobInfo info, Runnable runnable) - { - new Thread(runnable, "LobLoader").start(); - } - - public void close() - { - LifecycleUtil.deactivate(this, OMLogger.Level.DEBUG); - } - - /** - * @since 2.0 - */ - public boolean isClosed() - { - return !isActive(); - } - - /** - * @since 2.0 - */ - public CDOSession.Options options() - { - return options; - } - - /** - * @since 2.0 - */ - protected CDOSession.Options createOptions() - { - return new OptionsImpl(); - } - - public Object processPackage(Object value) - { - CDOFactoryImpl.prepareDynamicEPackage(value); - return value; - } - - public EPackage[] loadPackages(CDOPackageUnit packageUnit) - { - if (packageUnit.getOriginalType().isGenerated()) - { - if (!options().isGeneratedPackageEmulationEnabled()) - { - throw new CDOException(MessageFormat.format(Messages.getString("CDOSessionImpl.0"), packageUnit)); //$NON-NLS-1$ - } - } - - return getSessionProtocol().loadPackages(packageUnit); - } - - public void acquireAtomicRequestLock(Object key) - { - try - { - lockManager.lock(LockType.WRITE, key, this, IRWLockManager.WAIT); - } - catch (InterruptedException ex) - { - throw WrappedException.wrap(ex); - } - } - - public void releaseAtomicRequestLock(Object key) - { - lockManager.unlock(LockType.WRITE, key, singletonCollection); - } - - @Override - protected void initViewSynced(InternalCDOView view) - { - view.setSession(this); - view.setLastUpdateTime(getLastUpdateTime()); - } - - @Override - protected CDOBranch getMainBranch() - { - return getBranchManager().getMainBranch(); - } - - /** - * @since 2.0 - */ - public long refresh() - { - checkActive(); - if (options().isPassiveUpdateEnabled()) - { - return CDOBranchPoint.UNSPECIFIED_DATE; - } - - return refresh(false); - } - - private long refresh(boolean enablePassiveUpdates) - { - Map<CDOBranch, List<InternalCDOView>> views = new HashMap<CDOBranch, List<InternalCDOView>>(); - Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions = new HashMap<CDOBranch, Map<CDOID, InternalCDORevision>>(); - collectViewedRevisions(views, viewedRevisions); - cleanupRevisionCache(viewedRevisions); - - CDOSessionProtocol sessionProtocol = getSessionProtocol(); - long lastUpdateTime = getLastUpdateTime(); - int initialChunkSize = options().getCollectionLoadingPolicy().getInitialChunkSize(); - - RefreshSessionResult result = sessionProtocol.refresh(lastUpdateTime, viewedRevisions, initialChunkSize, - enablePassiveUpdates); - - setLastUpdateTime(result.getLastUpdateTime()); - registerPackageUnits(result.getPackageUnits()); - - for (Entry<CDOBranch, List<InternalCDOView>> entry : views.entrySet()) - { - CDOBranch branch = entry.getKey(); - List<InternalCDOView> branchViews = entry.getValue(); - processRefreshSessionResult(result, branch, branchViews, viewedRevisions); - } - - return result.getLastUpdateTime(); - } - - public void processRefreshSessionResult(RefreshSessionResult result, CDOBranch branch, - List<InternalCDOView> branchViews, Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions) - { - Map<CDOID, InternalCDORevision> oldRevisions = viewedRevisions.get(branch); - - List<CDORevisionKey> changedObjects = new ArrayList<CDORevisionKey>(); - List<InternalCDORevision> newRevisions = result.getChangedObjects(branch); - for (InternalCDORevision newRevision : newRevisions) - { - getRevisionManager().addRevision(newRevision); - - InternalCDORevision oldRevision = oldRevisions.get(newRevision.getID()); - InternalCDORevisionDelta delta = newRevision.compare(oldRevision); - changedObjects.add(delta); - } - - List<CDOIDAndVersion> detachedObjects = result.getDetachedObjects(branch); - for (CDOIDAndVersion detachedObject : detachedObjects) - { - getRevisionManager().reviseLatest(detachedObject.getID(), branch); - } - - for (InternalCDOView view : branchViews) - { - view.invalidate(view.getBranch(), result.getLastUpdateTime(), changedObjects, detachedObjects, oldRevisions, - false); - } - } - - private void collectViewedRevisions(Map<CDOBranch, List<InternalCDOView>> views, - Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions) - { - for (InternalCDOView view : getViews()) - { - if (view.getTimeStamp() == CDOView.UNSPECIFIED_DATE) - { - CDOBranch branch = view.getBranch(); - Map<CDOID, InternalCDORevision> revisions = viewedRevisions.get(branch); - boolean needNewMap = revisions == null; - if (needNewMap) - { - revisions = new HashMap<CDOID, InternalCDORevision>(); - } - - view.collectViewedRevisions(revisions); - if (!revisions.isEmpty()) - { - List<InternalCDOView> list = views.get(branch); - if (list == null) - { - list = new ArrayList<InternalCDOView>(); - views.put(branch, list); - } - - list.add(view); - - if (needNewMap) - { - viewedRevisions.put(branch, revisions); - } - } - } - } - } - - private void cleanupRevisionCache(Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions) - { - Set<InternalCDORevision> set = new HashSet<InternalCDORevision>(); - for (Map<CDOID, InternalCDORevision> revisions : viewedRevisions.values()) - { - for (InternalCDORevision revision : revisions.values()) - { - set.add(revision); - } - } - - InternalCDORevisionCache cache = getRevisionManager().getCache(); - List<CDORevision> currentRevisions = cache.getCurrentRevisions(); - for (CDORevision revision : currentRevisions) - { - if (!set.contains(revision)) - { - cache.removeRevision(revision.getID(), revision); - } - } - } - - public long getLastUpdateTime() - { - synchronized (lastUpdateTimeLock) - { - return lastUpdateTime; - } - } - - public void setLastUpdateTime(long lastUpdateTime) - { - synchronized (lastUpdateTimeLock) - { - if (this.lastUpdateTime < lastUpdateTime) - { - this.lastUpdateTime = lastUpdateTime; - } - - lastUpdateTimeLock.notifyAll(); - } - } - - public void waitForUpdate(long updateTime) - { - waitForUpdate(updateTime, NO_TIMEOUT); - } - - public boolean waitForUpdate(long updateTime, long timeoutMillis) - { - long end = timeoutMillis == NO_TIMEOUT ? Long.MAX_VALUE : System.currentTimeMillis() + timeoutMillis; - InternalCDOView views[] = getViews(); - if (views.length > 0) - { - for (CDOView view : views) - { - long viewTimeoutMillis = timeoutMillis == NO_TIMEOUT ? NO_TIMEOUT : end - System.currentTimeMillis(); - boolean ok = view.waitForUpdate(updateTime, viewTimeoutMillis); - if (!ok) - { - return false; - } - } - - return true; - } - - // Session without views - for (;;) - { - synchronized (lastUpdateTimeLock) - { - if (lastUpdateTime >= updateTime) - { - return true; - } - - long now = System.currentTimeMillis(); - if (now >= end) - { - return false; - } - - try - { - lastUpdateTimeLock.wait(end - now); - } - catch (InterruptedException ex) - { - throw WrappedException.wrap(ex); - } - } - } - } - - /** - * @since 3.0 - */ - public Object resolveElementProxy(CDORevision revision, EStructuralFeature feature, int accessIndex, int serverIndex) - { - if (!((InternalCDORevision)revision).isUnchunked()) - { - CDOCollectionLoadingPolicy policy = options().getCollectionLoadingPolicy(); - return policy.resolveProxy(revision, feature, accessIndex, serverIndex); - } - - return revision.data().get(feature, accessIndex); - } - - /** - * @since 4.0 - */ - public void resolveAllElementProxies(CDORevision revision) - { - if (!((InternalCDORevision)revision).isUnchunked()) - { - CDOCollectionLoadingPolicy policy = options().getCollectionLoadingPolicy(); - for (EStructuralFeature feature : revision.getEClass().getEAllStructuralFeatures()) - { - if (feature instanceof EReference) - { - EReference reference = (EReference)feature; - if (reference.isMany() && EMFUtil.isPersistent(reference)) - { - CDOList list = ((InternalCDORevision)revision).getList(reference); - for (Iterator<Object> it = list.iterator(); it.hasNext();) - { - Object element = it.next(); - if (element instanceof CDOElementProxy) - { - policy.resolveAllProxies(revision, reference); - break; - } - } - } - } - } - - ((InternalCDORevision)revision).setUnchunked(); - } - } - - public void handleRepositoryTypeChanged(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType) - { - fireEvent(new RepositoryTypeChangedEvent(this, oldType, newType)); - } - - public void handleRepositoryStateChanged(CDOCommonRepository.State oldState, CDOCommonRepository.State newState) - { - fireEvent(new RepositoryStateChangedEvent(this, oldState, newState)); - } - - public void handleBranchNotification(InternalCDOBranch branch) - { - getBranchManager().handleBranchCreated(branch); - } - - public void handleCommitNotification(CDOCommitInfo commitInfo) - { - try - { - registerPackageUnits(commitInfo.getNewPackageUnits()); - invalidate(commitInfo, null); - } - catch (RuntimeException ex) - { - if (isActive()) - { - OM.LOG.error(ex); - } - else - { - OM.LOG.info(Messages.getString("CDOSessionImpl.2")); //$NON-NLS-1$ - } - } - } - - public void handleLockNotification(CDOLockChangeInfo lockChangeInfo, InternalCDOView sender) - { - for (InternalCDOView view : getViews()) - { - if (view != sender) - { - view.handleLockNotification(sender, lockChangeInfo); - } - } - - fireEvent(new LocksChangedEvent(sender, lockChangeInfo)); - } - - private void registerPackageUnits(List<CDOPackageUnit> packageUnits) - { - InternalCDOPackageRegistry packageRegistry = getPackageRegistry(); - for (CDOPackageUnit newPackageUnit : packageUnits) - { - packageRegistry.putPackageUnit((InternalCDOPackageUnit)newPackageUnit); - } - } - - private Map<CDOID, InternalCDORevision> reviseRevisions(CDOCommitInfo commitInfo) - { - Map<CDOID, InternalCDORevision> oldRevisions = null; - CDOBranch newBranch = commitInfo.getBranch(); - long timeStamp = commitInfo.getTimeStamp(); - InternalCDORevisionManager revisionManager = getRevisionManager(); - - // Cache new revisions - for (CDOIDAndVersion key : commitInfo.getNewObjects()) - { - if (key instanceof InternalCDORevision) - { - InternalCDORevision newRevision = (InternalCDORevision)key; - revisionManager.addRevision(newRevision); - } - } - - // Apply deltas and cache the resulting new revisions, if possible... - for (CDORevisionKey key : commitInfo.getChangedObjects()) - { - // Add old values to revision deltas. - if (key instanceof CDORevisionDelta) - { - final CDORevisionDelta revisionDelta = (CDORevisionDelta)key; - final CDORevision oldRevision = revisionManager.getRevisionByVersion(revisionDelta.getID(), revisionDelta, - CDORevision.UNCHUNKED, false); - - if (oldRevision != null) - { - CDOFeatureDeltaVisitor visitor = new CDOFeatureDeltaVisitorImpl() - { - private List<Object> workList; - - @Override - public void visit(CDOAddFeatureDelta delta) - { - workList.add(delta.getIndex(), delta.getValue()); - } - - @Override - public void visit(CDOClearFeatureDelta delta) - { - workList.clear(); - } - - @Override - public void visit(CDOListFeatureDelta deltas) - { - @SuppressWarnings("unchecked") - List<Object> list = (List<Object>)((InternalCDORevision)oldRevision).getValue(deltas.getFeature()); - if (list != null) - { - workList = new ArrayList<Object>(list); - super.visit(deltas); - } - } - - @Override - public void visit(CDOMoveFeatureDelta delta) - { - Object value = workList.get(delta.getOldPosition()); - ((CDOMoveFeatureDeltaImpl)delta).setValue(value); - ECollections.move(workList, delta.getNewPosition(), delta.getOldPosition()); - } - - @Override - public void visit(CDORemoveFeatureDelta delta) - { - Object oldValue = workList.remove(delta.getIndex()); - ((CDOSingleValueFeatureDeltaImpl)delta).setValue(oldValue); - } - - @Override - public void visit(CDOSetFeatureDelta delta) - { - EStructuralFeature feature = delta.getFeature(); - Object value = null; - if (feature.isMany()) - { - value = workList.set(delta.getIndex(), delta.getValue()); - } - else - { - value = ((InternalCDORevision)oldRevision).getValue(feature); - } - - ((CDOSetFeatureDeltaImpl)delta).setOldValue(value); - } - }; - - for (CDOFeatureDelta featureDelta : revisionDelta.getFeatureDeltas()) - { - featureDelta.accept(visitor); - } - } - } - - CDOID id = key.getID(); - Pair<InternalCDORevision, InternalCDORevision> pair = createNewRevision(key, commitInfo); - if (pair != null) - { - InternalCDORevision newRevision = pair.getElement2(); - revisionManager.addRevision(newRevision); - if (oldRevisions == null) - { - oldRevisions = new HashMap<CDOID, InternalCDORevision>(); - } - - InternalCDORevision oldRevision = pair.getElement1(); - oldRevisions.put(id, oldRevision); - } - else - { - // ... otherwise try to revise old revision if it is in the same branch - if (ObjectUtil.equals(key.getBranch(), newBranch)) - { - revisionManager.reviseVersion(id, key, timeStamp); - } - } - } - - // Revise old revisions - for (CDOIDAndVersion key : commitInfo.getDetachedObjects()) - { - CDOID id = key.getID(); - int version = key.getVersion(); - if (version == CDOBranchVersion.UNSPECIFIED_VERSION) - { - revisionManager.reviseLatest(id, newBranch); - } - else - { - CDOBranchVersion branchVersion = newBranch.getVersion(version); - revisionManager.reviseVersion(id, branchVersion, timeStamp); - } - } - - return oldRevisions; - } - - private Pair<InternalCDORevision, InternalCDORevision> createNewRevision(CDORevisionKey potentialDelta, - CDOCommitInfo commitInfo) - { - if (potentialDelta instanceof CDORevisionDelta) - { - CDORevisionDelta delta = (CDORevisionDelta)potentialDelta; - CDOID id = delta.getID(); - - InternalCDORevisionManager revisionManager = getRevisionManager(); - InternalCDORevision oldRevision = revisionManager.getRevisionByVersion(id, potentialDelta, CDORevision.UNCHUNKED, - false); - if (oldRevision != null) - { - InternalCDORevision newRevision = oldRevision.copy(); - newRevision.adjustForCommit(commitInfo.getBranch(), commitInfo.getTimeStamp()); - - CDORevisable target = delta.getTarget(); - if (target != null) - { - newRevision.setVersion(target.getVersion()); - } - - delta.apply(newRevision); - newRevision.freeze(); - return new Pair<InternalCDORevision, InternalCDORevision>(oldRevision, newRevision); - } - } - - return null; - } - - /** - * @since 2.0 - */ - public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender) - { - long previousTimeStamp = commitInfo.getPreviousTimeStamp(); - long lastUpdateTime = getLastUpdateTime(); - - if (previousTimeStamp < lastUpdateTime) - { - previousTimeStamp = lastUpdateTime; - } - - synchronized (outOfSequenceInvalidations) - { - outOfSequenceInvalidations.put(previousTimeStamp, new Pair<CDOCommitInfo, InternalCDOTransaction>(commitInfo, - sender)); - } - - long nextPreviousTimeStamp = lastUpdateTime; - for (;;) - { - synchronized (outOfSequenceInvalidations) - { - Pair<CDOCommitInfo, InternalCDOTransaction> currentPair = outOfSequenceInvalidations - .remove(nextPreviousTimeStamp); - - // If we don't have the invalidation that follows the last one we processed, - // then there is nothing we can do right now - if (currentPair == null) - { - break; - } - - final CDOCommitInfo currentCommitInfo = currentPair.getElement1(); - final InternalCDOTransaction currentSender = currentPair.getElement2(); - nextPreviousTimeStamp = currentCommitInfo.getTimeStamp(); - - if (sender == null) - { - QueueRunner invalidationRunner = getInvalidationRunner(); - invalidationRunner.addWork(new Runnable() - { - public void run() - { - invalidateOrdered(currentCommitInfo, currentSender); - } - }); - } - else - { - invalidateOrdered(currentCommitInfo, currentSender); - } - } - } - } - - /** - * This method is synchronized on outOfSequenceInvalidations by the caller! - */ - private QueueRunner getInvalidationRunner() - { - if (invalidationRunner == null) - { - invalidationRunner = new QueueRunner(); - invalidationRunner.activate(); - } - - return invalidationRunner; - } - - private void invalidateOrdered(CDOCommitInfo commitInfo, InternalCDOTransaction sender) - { - Map<CDOID, InternalCDORevision> oldRevisions = null; - boolean success = commitInfo.getBranch() != null; - if (success) - { - oldRevisions = reviseRevisions(commitInfo); - } - - if (options.isPassiveUpdateEnabled()) - { - setLastUpdateTime(commitInfo.getTimeStamp()); - } - - if (success) - { - fireInvalidationEvent(sender, commitInfo); - } - - for (InternalCDOView view : getViews()) - { - if (view != sender) - { - invalidateView(commitInfo, view, oldRevisions); - } - else - { - view.setLastUpdateTime(commitInfo.getTimeStamp()); - } - } - } - - private void invalidateView(CDOCommitInfo commitInfo, InternalCDOView view, - Map<CDOID, InternalCDORevision> oldRevisions) - { - try - { - CDOBranch branch = commitInfo.getBranch(); - long lastUpdateTime = commitInfo.getTimeStamp(); - List<CDORevisionKey> allChangedObjects = commitInfo.getChangedObjects(); - List<CDOIDAndVersion> allDetachedObjects = commitInfo.getDetachedObjects(); - view.invalidate(branch, lastUpdateTime, allChangedObjects, allDetachedObjects, oldRevisions, true); - } - catch (RuntimeException ex) - { - if (view.isActive()) - { - OM.LOG.error(ex); - } - else - { - OM.LOG.info(Messages.getString("CDOSessionImpl.1")); //$NON-NLS-1$ - } - } - } - - /** - * @since 2.0 - */ - public void fireInvalidationEvent(InternalCDOTransaction sender, CDOCommitInfo commitInfo) - { - fireEvent(new InvalidationEvent(sender, commitInfo)); - } - - @Override - public String toString() - { - String name = repositoryInfo == null ? "?" : repositoryInfo.getName(); //$NON-NLS-1$ - return MessageFormat.format("Session{0} [{1}]", sessionID, name); //$NON-NLS-1$ - } - - public CDOBranchPoint getCommittedSinceLastRefresh(CDOID id) - { - if (isSticky()) - { - return committedSinceLastRefresh.get(id); - } - - return null; - } - - public void setCommittedSinceLastRefresh(CDOID id, CDOBranchPoint branchPoint) - { - if (isSticky()) - { - committedSinceLastRefresh.put(id, branchPoint); - } - } - - public void clearCommittedSinceLastRefresh() - { - if (isSticky()) - { - committedSinceLastRefresh.clear(); - } - } - - public boolean isSticky() - { - return !options().isPassiveUpdateEnabled() && getRepositoryInfo().isSupportingAudits(); - } - - public CDOChangeSetData compareRevisions(CDOBranchPoint source, CDOBranchPoint target) - { - long now = getLastUpdateTime(); - - if (target.getTimeStamp() == CDOBranchPoint.UNSPECIFIED_DATE) - { - target = target.getBranch().getPoint(now); - } - - if (source.getTimeStamp() == CDOBranchPoint.UNSPECIFIED_DATE) - { - source = source.getBranch().getPoint(now); - } - - CDORevisionAvailabilityInfo targetInfo = createRevisionAvailabilityInfo(target); - CDORevisionAvailabilityInfo sourceInfo = createRevisionAvailabilityInfo(source); - - Set<CDOID> ids = sessionProtocol.loadMergeData(targetInfo, sourceInfo, null, null); - - cacheRevisions(targetInfo); - cacheRevisions(sourceInfo); - - return CDORevisionUtil.createChangeSetData(ids, sourceInfo, targetInfo); - } - - public CDORevisionAvailabilityInfo createRevisionAvailabilityInfo(CDOBranchPoint branchPoint) - { - CDORevisionAvailabilityInfo info = new CDORevisionAvailabilityInfo(branchPoint); - - InternalCDORevisionManager revisionManager = getRevisionManager(); - InternalCDORevisionCache cache = revisionManager.getCache(); - - List<CDORevision> revisions = cache.getRevisions(branchPoint); - for (CDORevision revision : revisions) - { - if (revision instanceof PointerCDORevision) - { - PointerCDORevision pointer = (PointerCDORevision)revision; - CDOBranchVersion target = pointer.getTarget(); - if (target != null) - { - revision = cache.getRevisionByVersion(pointer.getID(), target); - } - } - else if (revision instanceof DetachedCDORevision) - { - revision = null; - } - - if (revision != null) - { - resolveAllElementProxies(revision); - info.addRevision(revision); - } - } - - return info; - } - - public void cacheRevisions(CDORevisionAvailabilityInfo info) - { - InternalCDORevisionManager revisionManager = getRevisionManager(); - CDOBranch branch = info.getBranchPoint().getBranch(); - for (CDORevisionKey key : info.getAvailableRevisions().values()) - { - CDORevision revision = (CDORevision)key; - revisionManager.addRevision(revision); - - if (!ObjectUtil.equals(revision.getBranch(), branch)) - { - CDOID id = revision.getID(); - CDORevision firstRevision = revisionManager.getCache().getRevisionByVersion(id, - branch.getVersion(CDOBranchVersion.FIRST_VERSION)); - if (firstRevision != null) - { - long revised = firstRevision.getTimeStamp() - 1L; - CDOBranchVersion target = CDOBranchUtil.copyBranchVersion(revision); - PointerCDORevision pointer = new PointerCDORevision(revision.getEClass(), id, branch, revised, target); - revisionManager.addRevision(pointer); - } - } - } - } - - @Override - protected void doActivate() throws Exception - { - super.doActivate(); - - InternalCDORemoteSessionManager remoteSessionManager = new CDORemoteSessionManagerImpl(); - remoteSessionManager.setLocalSession(this); - setRemoteSessionManager(remoteSessionManager); - remoteSessionManager.activate(); - - checkState(sessionProtocol, "sessionProtocol"); //$NON-NLS-1$ - checkState(remoteSessionManager, "remoteSessionManager"); //$NON-NLS-1$ - } - - @Override - protected void doDeactivate() throws Exception - { - super.doDeactivate(); - - LifecycleUtil.deactivate(invalidationRunner); - outOfSequenceInvalidations.clear(); - - unhookSessionProtocol(); - - CDORemoteSessionManager remoteSessionManager = getRemoteSessionManager(); - setRemoteSessionManager(null); - LifecycleUtil.deactivate(remoteSessionManager); - - CDOSessionProtocol sessionProtocol = getSessionProtocol(); - LifecycleUtil.deactivate(sessionProtocol); - setSessionProtocol(null); - } - - /** - * Makes this session start listening to its protocol - */ - protected CDOSessionProtocol hookSessionProtocol() - { - EventUtil.addListener(sessionProtocol, sessionProtocolListener); - return sessionProtocol; - } - - /** - * Makes this session stop listening to its protocol - */ - protected void unhookSessionProtocol() - { - EventUtil.removeListener(sessionProtocol, sessionProtocolListener); - } - - protected void sessionProtocolDeactivated() - { - deactivate(); - } - - /** - * A separate class for better monitor debugging. - * - * @author Eike Stepper - */ - private static final class LastUpdateTimeLock - { - } - - /** - * @author Eike Stepper - */ - private static final class OutOfSequenceInvalidations extends - HashMap<Long, Pair<CDOCommitInfo, InternalCDOTransaction>> - { - private static final long serialVersionUID = 1L; - } - - /** - * @author Eike Stepper - * @since 2.0 - */ - protected class OptionsImpl extends Notifier implements Options - { - private boolean generatedPackageEmulationEnabled; - - private boolean passiveUpdateEnabled = true; - - private PassiveUpdateMode passiveUpdateMode = PassiveUpdateMode.INVALIDATIONS; - - private LockNotificationMode lockNotificationMode = LockNotificationMode.IF_REQUIRED_BY_VIEWS; - - private CDOCollectionLoadingPolicy collectionLoadingPolicy; - - private CDOLobStore lobCache = CDOLobStoreImpl.INSTANCE; - - public OptionsImpl() - { - setCollectionLoadingPolicy(null); // Init default - } - - public CDOSession getContainer() - { - return CDOSessionImpl.this; - } - - public boolean isGeneratedPackageEmulationEnabled() - { - return generatedPackageEmulationEnabled; - } - - public synchronized void setGeneratedPackageEmulationEnabled(boolean generatedPackageEmulationEnabled) - { - this.generatedPackageEmulationEnabled = generatedPackageEmulationEnabled; - if (this.generatedPackageEmulationEnabled != generatedPackageEmulationEnabled) - { - this.generatedPackageEmulationEnabled = generatedPackageEmulationEnabled; - // TODO Check inconsistent state if switching off? - - IListener[] listeners = getListeners(); - if (listeners != null) - { - fireEvent(new GeneratedPackageEmulationEventImpl(), listeners); - } - } - } - - public boolean isPassiveUpdateEnabled() - { - return passiveUpdateEnabled; - } - - public synchronized void setPassiveUpdateEnabled(boolean passiveUpdateEnabled) - { - if (this.passiveUpdateEnabled != passiveUpdateEnabled) - { - this.passiveUpdateEnabled = passiveUpdateEnabled; - CDOSessionProtocol protocol = getSessionProtocol(); - if (protocol != null) - { - if (passiveUpdateEnabled) - { - refresh(true); - } - else - { - protocol.disablePassiveUpdate(); - } - - IListener[] listeners = getListeners(); - if (listeners != null) - { - fireEvent(new PassiveUpdateEventImpl(!passiveUpdateEnabled, passiveUpdateEnabled, passiveUpdateMode, - passiveUpdateMode), listeners); - } - } - } - } - - public PassiveUpdateMode getPassiveUpdateMode() - { - return passiveUpdateMode; - } - - public void setPassiveUpdateMode(PassiveUpdateMode passiveUpdateMode) - { - checkArg(passiveUpdateMode, "passiveUpdateMode"); //$NON-NLS-1$ - if (this.passiveUpdateMode != passiveUpdateMode) - { - PassiveUpdateMode oldMode = this.passiveUpdateMode; - this.passiveUpdateMode = passiveUpdateMode; - CDOSessionProtocol protocol = getSessionProtocol(); - if (protocol != null) - { - protocol.setPassiveUpdateMode(passiveUpdateMode); - - IListener[] listeners = getListeners(); - if (listeners != null) - { - fireEvent( - new PassiveUpdateEventImpl(passiveUpdateEnabled, passiveUpdateEnabled, oldMode, passiveUpdateMode), - listeners); - } - } - } - } - - public LockNotificationMode getLockNotificationMode() - { - return lockNotificationMode; - } - - public void setLockNotificationMode(LockNotificationMode lockNotificationMode) - { - checkArg(lockNotificationMode, "lockNotificationMode"); //$NON-NLS-1$ - if (this.lockNotificationMode != lockNotificationMode) - { - LockNotificationMode oldMode = this.lockNotificationMode; - this.lockNotificationMode = lockNotificationMode; - CDOSessionProtocol protocol = getSessionProtocol(); - if (protocol != null) - { - protocol.setLockNotificationMode(lockNotificationMode); - - IListener[] listeners = getListeners(); - if (listeners != null) - { - fireEvent(new LockNotificationModeEventImpl(oldMode, lockNotificationMode), listeners); - } - } - } - this.lockNotificationMode = lockNotificationMode; - } - - public CDOCollectionLoadingPolicy getCollectionLoadingPolicy() - { - synchronized (this) - { - return collectionLoadingPolicy; - } - } - - public void setCollectionLoadingPolicy(CDOCollectionLoadingPolicy policy) - { - if (policy == null) - { - policy = CDOUtil.createCollectionLoadingPolicy(CDORevision.UNCHUNKED, CDORevision.UNCHUNKED); - } - - CDOSession oldSession = policy.getSession(); - if (oldSession != null) - { - throw new IllegalArgumentException("Policy is already associated with " + oldSession); - } - - policy.setSession(CDOSessionImpl.this); - - IListener[] listeners = getListeners(); - IEvent event = null; - - synchronized (this) - { - if (collectionLoadingPolicy != policy) - { - collectionLoadingPolicy = policy; - if (listeners != null) - { - event = new CollectionLoadingPolicyEventImpl(); - } - } - } - - if (event != null) - { - fireEvent(event, listeners); - } - } - - public CDOLobStore getLobCache() - { - synchronized (this) - { - return lobCache; - } - } - - public void setLobCache(CDOLobStore cache) - { - if (cache == null) - { - cache = CDOLobStoreImpl.INSTANCE; - } - - IListener[] listeners = getListeners(); - IEvent event = null; - - synchronized (this) - { - if (lobCache != cache) - { - lobCache = cache; - if (listeners != null) - { - event = new LobCacheEventImpl(); - } - } - } - - if (event != null) - { - fireEvent(event, listeners); - } - } - - /** - * @author Eike Stepper - */ - private final class GeneratedPackageEmulationEventImpl extends OptionsEvent implements - GeneratedPackageEmulationEvent - { - private static final long serialVersionUID = 1L; - - public GeneratedPackageEmulationEventImpl() - { - super(OptionsImpl.this); - } - } - - /** - * @author Eike Stepper - */ - private final class PassiveUpdateEventImpl extends OptionsEvent implements PassiveUpdateEvent - { - private static final long serialVersionUID = 1L; - - private boolean oldEnabled; - - private boolean newEnabled; - - private PassiveUpdateMode oldMode; - - private PassiveUpdateMode newMode; - - public PassiveUpdateEventImpl(boolean oldEnabled, boolean newEnabled, PassiveUpdateMode oldMode, - PassiveUpdateMode newMode) - { - super(OptionsImpl.this); - this.oldEnabled = oldEnabled; - this.newEnabled = newEnabled; - this.oldMode = oldMode; - this.newMode = newMode; - } - - public boolean getOldEnabled() - { - return oldEnabled; - } - - public boolean getNewEnabled() - { - return newEnabled; - } - - public PassiveUpdateMode getOldMode() - { - return oldMode; - } - - public PassiveUpdateMode getNewMode() - { - return newMode; - } - } - - /** - * @author Caspar De Groot - */ - private final class LockNotificationModeEventImpl extends OptionsEvent implements LockNotificationModeEvent - { - private static final long serialVersionUID = 1L; - - private LockNotificationMode oldMode, newMode; - - public LockNotificationModeEventImpl(LockNotificationMode oldMode, LockNotificationMode newMode) - { - super(OptionsImpl.this); - this.oldMode = oldMode; - this.newMode = newMode; - } - - public LockNotificationMode getOldMode() - { - return oldMode; - } - - public LockNotificationMode getNewMode() - { - return newMode; - } - } - - /** - * @author Eike Stepper - */ - private final class CollectionLoadingPolicyEventImpl extends OptionsEvent implements CollectionLoadingPolicyEvent - { - private static final long serialVersionUID = 1L; - - public CollectionLoadingPolicyEventImpl() - { - super(OptionsImpl.this); - } - } - - /** - * @author Eike Stepper - */ - private final class LobCacheEventImpl extends OptionsEvent implements LobCacheEvent - { - private static final long serialVersionUID = 1L; - - public LobCacheEventImpl() - { - super(OptionsImpl.this); - } - } - } - - /** - * @author Eike Stepper - */ - private final class InvalidationEvent extends Event implements CDOSessionInvalidationEvent - { - private static final long serialVersionUID = 1L; - - private InternalCDOTransaction sender; - - private CDOCommitInfo commitInfo; - - public InvalidationEvent(InternalCDOTransaction sender, CDOCommitInfo commitInfo) - { - super(CDOSessionImpl.this); - this.sender = sender; - this.commitInfo = commitInfo; - } - - @Override - public CDOSession getSource() - { - return (CDOSession)super.getSource(); - } - - public CDOCommitInfoManager getCommitInfoManager() - { - return commitInfo.getCommitInfoManager(); - } - - public CDOTransaction getLocalTransaction() - { - return sender; - } - - @Deprecated - public InternalCDOView getView() - { - return sender; - } - - public boolean isRemote() - { - return sender == null; - } - - public CDOBranch getBranch() - { - return commitInfo.getBranch(); - } - - public long getTimeStamp() - { - return commitInfo.getTimeStamp(); - } - - public long getPreviousTimeStamp() - { - return commitInfo.getPreviousTimeStamp(); - } - - public String getUserID() - { - return commitInfo.getUserID(); - } - - public String getComment() - { - return commitInfo.getComment(); - } - - public boolean isEmpty() - { - return false; - } - - public CDOChangeSetData copy() - { - return commitInfo.copy(); - } - - public void merge(CDOChangeSetData changeSetData) - { - commitInfo.merge(changeSetData); - } - - public List<CDOPackageUnit> getNewPackageUnits() - { - return commitInfo.getNewPackageUnits(); - } - - public List<CDOIDAndVersion> getNewObjects() - { - return commitInfo.getNewObjects(); - } - - public List<CDORevisionKey> getChangedObjects() - { - return commitInfo.getChangedObjects(); - } - - public List<CDOIDAndVersion> getDetachedObjects() - { - return commitInfo.getDetachedObjects(); - } - - public Map<CDOID, CDOChangeKind> getChangeKinds() - { - return commitInfo.getChangeKinds(); - } - - public CDOChangeKind getChangeKind(CDOID id) - { - return commitInfo.getChangeKind(id); - } - - @Override - public String toString() - { - return "CDOSessionInvalidationEvent[" + commitInfo + "]"; //$NON-NLS-1$ //$NON-NLS-2$ - } - } - - /** - * @author Caspar De Groot - * @since 4.1 - */ - private final class LocksChangedEvent extends DefaultLocksChangedEvent implements CDOSessionLocksChangedEvent - { - private static final long serialVersionUID = 1L; - - public LocksChangedEvent(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo) - { - super(CDOSessionImpl.this, sender, lockChangeInfo); - } - - @Override - public CDOSession getSource() - { - return (CDOSession)super.getSource(); - } - } -} +/*
+ * 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 226778
+ * Simon McDuff - bug 230832
+ * Simon McDuff - bug 233490
+ * Simon McDuff - bug 213402
+ * Victor Roldan Betancort - maintenance
+ */
+package org.eclipse.emf.internal.cdo.session;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+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.CDOChangeKind;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+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.CDOIDGenerator;
+import org.eclipse.emf.cdo.common.lob.CDOLobInfo;
+import org.eclipse.emf.cdo.common.lob.CDOLobStore;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator;
+import org.eclipse.emf.cdo.common.revision.CDOElementProxy;
+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.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+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.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+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.CDOException;
+import org.eclipse.emf.cdo.common.util.RepositoryStateChangedEvent;
+import org.eclipse.emf.cdo.common.util.RepositoryTypeChangedEvent;
+import org.eclipse.emf.cdo.eresource.EresourcePackage;
+import org.eclipse.emf.cdo.etypes.EtypesPackage;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOMoveFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOSetFeatureDeltaImpl;
+import org.eclipse.emf.cdo.internal.common.revision.delta.CDOSingleValueFeatureDeltaImpl;
+import org.eclipse.emf.cdo.session.CDOCollectionLoadingPolicy;
+import org.eclipse.emf.cdo.session.CDORepositoryInfo;
+import org.eclipse.emf.cdo.session.CDOSession;
+import org.eclipse.emf.cdo.session.CDOSessionInvalidationEvent;
+import org.eclipse.emf.cdo.session.CDOSessionLocksChangedEvent;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSessionManager;
+import org.eclipse.emf.cdo.spi.common.CDOLobStoreImpl;
+import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+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.DetachedCDORevision;
+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.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.util.CDOUtil;
+import org.eclipse.emf.cdo.view.CDOFetchRuleManager;
+import org.eclipse.emf.cdo.view.CDOView;
+
+import org.eclipse.emf.internal.cdo.analyzer.NOOPFetchRuleManager;
+import org.eclipse.emf.internal.cdo.bundle.OM;
+import org.eclipse.emf.internal.cdo.messages.Messages;
+import org.eclipse.emf.internal.cdo.object.CDOFactoryImpl;
+import org.eclipse.emf.internal.cdo.session.remote.CDORemoteSessionManagerImpl;
+import org.eclipse.emf.internal.cdo.util.DefaultLocksChangedEvent;
+
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.concurrent.IRWLockManager;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.concurrent.IRWOLockManager;
+import org.eclipse.net4j.util.concurrent.QueueRunner;
+import org.eclipse.net4j.util.concurrent.RWOLockManager;
+import org.eclipse.net4j.util.event.Event;
+import org.eclipse.net4j.util.event.EventUtil;
+import org.eclipse.net4j.util.event.IEvent;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.event.Notifier;
+import org.eclipse.net4j.util.io.IOUtil;
+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.net4j.util.options.OptionsEvent;
+
+import org.eclipse.emf.common.util.ECollections;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.RefreshSessionResult;
+import org.eclipse.emf.spi.cdo.InternalCDORemoteSessionManager;
+import org.eclipse.emf.spi.cdo.InternalCDOSession;
+import org.eclipse.emf.spi.cdo.InternalCDOTransaction;
+import org.eclipse.emf.spi.cdo.InternalCDOView;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class CDOSessionImpl extends CDOTransactionContainerImpl implements InternalCDOSession
+{
+ private ExceptionHandler exceptionHandler;
+
+ private CDOIDGenerator idGenerator;
+
+ private InternalCDOPackageRegistry packageRegistry;
+
+ private InternalCDOBranchManager branchManager;
+
+ private InternalCDORevisionManager revisionManager;
+
+ private InternalCDOCommitInfoManager commitInfoManager;
+
+ private CDOSessionProtocol sessionProtocol;
+
+ @ExcludeFromDump
+ private IListener sessionProtocolListener = new LifecycleEventAdapter()
+ {
+ @Override
+ protected void onDeactivated(ILifecycle lifecycle)
+ {
+ sessionProtocolDeactivated();
+ }
+ };
+
+ private int sessionID;
+
+ private String userID;
+
+ private long lastUpdateTime;
+
+ @ExcludeFromDump
+ private LastUpdateTimeLock lastUpdateTimeLock = new LastUpdateTimeLock();
+
+ private CDOSession.Options options = createOptions();
+
+ private OutOfSequenceInvalidations outOfSequenceInvalidations = new OutOfSequenceInvalidations();
+
+ private QueueRunner invalidationRunner;
+
+ private CDORepositoryInfo repositoryInfo;
+
+ private CDOFetchRuleManager fetchRuleManager;
+
+ private IRWOLockManager<CDOSessionImpl, Object> lockManager = new RWOLockManager<CDOSessionImpl, Object>();
+
+ @ExcludeFromDump
+ private Set<CDOSessionImpl> singletonCollection = Collections.singleton(this);
+
+ private boolean mainBranchLocal;
+
+ private CDOAuthenticator authenticator;
+
+ private InternalCDORemoteSessionManager remoteSessionManager;
+
+ /**
+ * A map to track for every object that was committed since this session's last refresh, onto what CDOBranchPoint it
+ * was committed. (Used only for sticky transactions, see bug 290032 - Sticky views.)
+ */
+ private Map<CDOID, CDOBranchPoint> committedSinceLastRefresh = new HashMap<CDOID, CDOBranchPoint>();
+
+ static
+ {
+ // Ensure that these 3 packages are registered with the global package registry in stand-alone
+ EcorePackage.eINSTANCE.getClass();
+ EresourcePackage.eINSTANCE.getClass();
+ EtypesPackage.eINSTANCE.getClass();
+ }
+
+ public CDOSessionImpl()
+ {
+ }
+
+ public CDORepositoryInfo getRepositoryInfo()
+ {
+ return repositoryInfo;
+ }
+
+ public void setRepositoryInfo(CDORepositoryInfo repositoryInfo)
+ {
+ this.repositoryInfo = repositoryInfo;
+ }
+
+ public int getSessionID()
+ {
+ return sessionID;
+ }
+
+ public void setSessionID(int sessionID)
+ {
+ this.sessionID = sessionID;
+ }
+
+ public String getUserID()
+ {
+ return userID;
+ }
+
+ public void setUserID(String userID)
+ {
+ this.userID = userID;
+ }
+
+ public ExceptionHandler getExceptionHandler()
+ {
+ return exceptionHandler;
+ }
+
+ public void setExceptionHandler(ExceptionHandler exceptionHandler)
+ {
+ checkInactive();
+ this.exceptionHandler = exceptionHandler;
+ }
+
+ public CDOIDGenerator getIDGenerator()
+ {
+ return idGenerator;
+ }
+
+ public void setIDGenerator(CDOIDGenerator idGenerator)
+ {
+ checkInactive();
+ this.idGenerator = idGenerator;
+ }
+
+ public InternalCDOPackageRegistry getPackageRegistry()
+ {
+ return packageRegistry;
+ }
+
+ public void setPackageRegistry(InternalCDOPackageRegistry packageRegistry)
+ {
+ this.packageRegistry = packageRegistry;
+ }
+
+ public InternalCDOBranchManager getBranchManager()
+ {
+ return branchManager;
+ }
+
+ public void setBranchManager(InternalCDOBranchManager branchManager)
+ {
+ checkInactive();
+ this.branchManager = branchManager;
+ }
+
+ public InternalCDORevisionManager getRevisionManager()
+ {
+ return revisionManager;
+ }
+
+ public void setRevisionManager(InternalCDORevisionManager revisionManager)
+ {
+ checkInactive();
+ this.revisionManager = revisionManager;
+ }
+
+ public InternalCDOCommitInfoManager getCommitInfoManager()
+ {
+ return commitInfoManager;
+ }
+
+ public void setCommitInfoManager(InternalCDOCommitInfoManager commitInfoManager)
+ {
+ checkInactive();
+ this.commitInfoManager = commitInfoManager;
+ }
+
+ public CDOSessionProtocol getSessionProtocol()
+ {
+ return sessionProtocol;
+ }
+
+ public void setSessionProtocol(CDOSessionProtocol sessionProtocol)
+ {
+ checkInactive();
+ if (exceptionHandler == null)
+ {
+ this.sessionProtocol = sessionProtocol;
+ }
+ else
+ {
+ if (this.sessionProtocol instanceof DelegatingSessionProtocol)
+ {
+ ((DelegatingSessionProtocol)this.sessionProtocol).setDelegate(sessionProtocol);
+ }
+ else
+ {
+ this.sessionProtocol = new DelegatingSessionProtocol(sessionProtocol, exceptionHandler);
+ }
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ public CDOFetchRuleManager getFetchRuleManager()
+ {
+ return fetchRuleManager;
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void setFetchRuleManager(CDOFetchRuleManager fetchRuleManager)
+ {
+ if (fetchRuleManager == null)
+ {
+ fetchRuleManager = new NOOPFetchRuleManager()
+ {
+ public CDOCollectionLoadingPolicy getCollectionLoadingPolicy()
+ {
+ return options().getCollectionLoadingPolicy();
+ }
+ };
+ }
+
+ this.fetchRuleManager = fetchRuleManager;
+ }
+
+ public CDOAuthenticator getAuthenticator()
+ {
+ return authenticator;
+ }
+
+ public void setAuthenticator(CDOAuthenticator authenticator)
+ {
+ this.authenticator = authenticator;
+ }
+
+ public boolean isMainBranchLocal()
+ {
+ return mainBranchLocal;
+ }
+
+ public void setMainBranchLocal(boolean mainBranchLocal)
+ {
+ this.mainBranchLocal = mainBranchLocal;
+ }
+
+ public InternalCDORemoteSessionManager getRemoteSessionManager()
+ {
+ return remoteSessionManager;
+ }
+
+ public void setRemoteSessionManager(InternalCDORemoteSessionManager remoteSessionManager)
+ {
+ this.remoteSessionManager = remoteSessionManager;
+ }
+
+ public CDOLobStore getLobStore()
+ {
+ final CDOLobStore cache = options().getLobCache();
+ return new CDOLobStore.Delegating()
+ {
+ @Override
+ public InputStream getBinary(final CDOLobInfo info) throws IOException
+ {
+ for (;;)
+ {
+ try
+ {
+ return super.getBinary(info);
+ }
+ catch (FileNotFoundException couldNotBeRead)
+ {
+ try
+ {
+ loadBinary(info);
+ }
+ catch (FileNotFoundException couldNotBeCreated)
+ {
+ // Try to read again
+ }
+ }
+ }
+ }
+
+ @Override
+ public Reader getCharacter(CDOLobInfo info) throws IOException
+ {
+ for (;;)
+ {
+ try
+ {
+ return super.getCharacter(info);
+ }
+ catch (FileNotFoundException couldNotBeRead)
+ {
+ try
+ {
+ loadCharacter(info);
+ }
+ catch (FileNotFoundException couldNotBeCreated)
+ {
+ // Try to read again
+ }
+ }
+ }
+ }
+
+ private void loadBinary(final CDOLobInfo info) throws IOException
+ {
+ final File file = getDelegate().getBinaryFile(info.getID());
+ final FileOutputStream out = new FileOutputStream(file);
+
+ loadLobAsync(info, new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ getSessionProtocol().loadLob(info, out);
+ }
+ catch (Throwable t)
+ {
+ OM.LOG.error(t);
+ IOUtil.delete(file);
+ }
+ }
+ });
+ }
+
+ private void loadCharacter(final CDOLobInfo info) throws IOException
+ {
+ final File file = getDelegate().getCharacterFile(info.getID());
+ final FileWriter out = new FileWriter(file);
+
+ loadLobAsync(info, new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ getSessionProtocol().loadLob(info, out);
+ }
+ catch (Throwable t)
+ {
+ OM.LOG.error(t);
+ IOUtil.delete(file);
+ }
+ }
+ });
+ }
+
+ @Override
+ protected CDOLobStore getDelegate()
+ {
+ return cache;
+ }
+ };
+ }
+
+ protected void loadLobAsync(CDOLobInfo info, Runnable runnable)
+ {
+ new Thread(runnable, "LobLoader").start();
+ }
+
+ public void close()
+ {
+ LifecycleUtil.deactivate(this, OMLogger.Level.DEBUG);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public boolean isClosed()
+ {
+ return !isActive();
+ }
+
+ /**
+ * @since 2.0
+ */
+ public CDOSession.Options options()
+ {
+ return options;
+ }
+
+ /**
+ * @since 2.0
+ */
+ protected CDOSession.Options createOptions()
+ {
+ return new OptionsImpl();
+ }
+
+ public Object processPackage(Object value)
+ {
+ CDOFactoryImpl.prepareDynamicEPackage(value);
+ return value;
+ }
+
+ public EPackage[] loadPackages(CDOPackageUnit packageUnit)
+ {
+ if (packageUnit.getOriginalType().isGenerated())
+ {
+ if (!options().isGeneratedPackageEmulationEnabled())
+ {
+ throw new CDOException(MessageFormat.format(Messages.getString("CDOSessionImpl.0"), packageUnit)); //$NON-NLS-1$
+ }
+ }
+
+ return getSessionProtocol().loadPackages(packageUnit);
+ }
+
+ public void acquireAtomicRequestLock(Object key)
+ {
+ try
+ {
+ lockManager.lock(LockType.WRITE, key, this, IRWLockManager.WAIT);
+ }
+ catch (InterruptedException ex)
+ {
+ throw WrappedException.wrap(ex);
+ }
+ }
+
+ public void releaseAtomicRequestLock(Object key)
+ {
+ lockManager.unlock(LockType.WRITE, key, singletonCollection);
+ }
+
+ @Override
+ protected void initViewSynced(InternalCDOView view)
+ {
+ view.setSession(this);
+ view.setLastUpdateTime(getLastUpdateTime());
+ }
+
+ @Override
+ protected CDOBranch getMainBranch()
+ {
+ return getBranchManager().getMainBranch();
+ }
+
+ /**
+ * @since 2.0
+ */
+ public long refresh()
+ {
+ checkActive();
+ if (options().isPassiveUpdateEnabled())
+ {
+ return CDOBranchPoint.UNSPECIFIED_DATE;
+ }
+
+ return refresh(false);
+ }
+
+ private long refresh(boolean enablePassiveUpdates)
+ {
+ Map<CDOBranch, List<InternalCDOView>> views = new HashMap<CDOBranch, List<InternalCDOView>>();
+ Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions = new HashMap<CDOBranch, Map<CDOID, InternalCDORevision>>();
+ collectViewedRevisions(views, viewedRevisions);
+ cleanupRevisionCache(viewedRevisions);
+
+ CDOSessionProtocol sessionProtocol = getSessionProtocol();
+ long lastUpdateTime = getLastUpdateTime();
+ int initialChunkSize = options().getCollectionLoadingPolicy().getInitialChunkSize();
+
+ RefreshSessionResult result = sessionProtocol.refresh(lastUpdateTime, viewedRevisions, initialChunkSize,
+ enablePassiveUpdates);
+
+ setLastUpdateTime(result.getLastUpdateTime());
+ registerPackageUnits(result.getPackageUnits());
+
+ for (Entry<CDOBranch, List<InternalCDOView>> entry : views.entrySet())
+ {
+ CDOBranch branch = entry.getKey();
+ List<InternalCDOView> branchViews = entry.getValue();
+ processRefreshSessionResult(result, branch, branchViews, viewedRevisions);
+ }
+
+ return result.getLastUpdateTime();
+ }
+
+ public void processRefreshSessionResult(RefreshSessionResult result, CDOBranch branch,
+ List<InternalCDOView> branchViews, Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions)
+ {
+ Map<CDOID, InternalCDORevision> oldRevisions = viewedRevisions.get(branch);
+
+ List<CDORevisionKey> changedObjects = new ArrayList<CDORevisionKey>();
+ List<InternalCDORevision> newRevisions = result.getChangedObjects(branch);
+ for (InternalCDORevision newRevision : newRevisions)
+ {
+ getRevisionManager().addRevision(newRevision);
+
+ InternalCDORevision oldRevision = oldRevisions.get(newRevision.getID());
+ InternalCDORevisionDelta delta = newRevision.compare(oldRevision);
+ changedObjects.add(delta);
+ }
+
+ List<CDOIDAndVersion> detachedObjects = result.getDetachedObjects(branch);
+ for (CDOIDAndVersion detachedObject : detachedObjects)
+ {
+ getRevisionManager().reviseLatest(detachedObject.getID(), branch);
+ }
+
+ for (InternalCDOView view : branchViews)
+ {
+ view.invalidate(view.getBranch(), result.getLastUpdateTime(), changedObjects, detachedObjects, oldRevisions,
+ false);
+ }
+ }
+
+ private void collectViewedRevisions(Map<CDOBranch, List<InternalCDOView>> views,
+ Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions)
+ {
+ for (InternalCDOView view : getViews())
+ {
+ if (view.getTimeStamp() == CDOView.UNSPECIFIED_DATE)
+ {
+ CDOBranch branch = view.getBranch();
+ Map<CDOID, InternalCDORevision> revisions = viewedRevisions.get(branch);
+ boolean needNewMap = revisions == null;
+ if (needNewMap)
+ {
+ revisions = new HashMap<CDOID, InternalCDORevision>();
+ }
+
+ view.collectViewedRevisions(revisions);
+ if (!revisions.isEmpty())
+ {
+ List<InternalCDOView> list = views.get(branch);
+ if (list == null)
+ {
+ list = new ArrayList<InternalCDOView>();
+ views.put(branch, list);
+ }
+
+ list.add(view);
+
+ if (needNewMap)
+ {
+ viewedRevisions.put(branch, revisions);
+ }
+ }
+ }
+ }
+ }
+
+ private void cleanupRevisionCache(Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions)
+ {
+ Set<InternalCDORevision> set = new HashSet<InternalCDORevision>();
+ for (Map<CDOID, InternalCDORevision> revisions : viewedRevisions.values())
+ {
+ for (InternalCDORevision revision : revisions.values())
+ {
+ set.add(revision);
+ }
+ }
+
+ InternalCDORevisionCache cache = getRevisionManager().getCache();
+ List<CDORevision> currentRevisions = cache.getCurrentRevisions();
+ for (CDORevision revision : currentRevisions)
+ {
+ if (!set.contains(revision))
+ {
+ cache.removeRevision(revision.getID(), revision);
+ }
+ }
+ }
+
+ public long getLastUpdateTime()
+ {
+ synchronized (lastUpdateTimeLock)
+ {
+ return lastUpdateTime;
+ }
+ }
+
+ public void setLastUpdateTime(long lastUpdateTime)
+ {
+ synchronized (lastUpdateTimeLock)
+ {
+ if (this.lastUpdateTime < lastUpdateTime)
+ {
+ this.lastUpdateTime = lastUpdateTime;
+ }
+
+ lastUpdateTimeLock.notifyAll();
+ }
+ }
+
+ public void waitForUpdate(long updateTime)
+ {
+ waitForUpdate(updateTime, NO_TIMEOUT);
+ }
+
+ public boolean waitForUpdate(long updateTime, long timeoutMillis)
+ {
+ long end = timeoutMillis == NO_TIMEOUT ? Long.MAX_VALUE : System.currentTimeMillis() + timeoutMillis;
+ InternalCDOView views[] = getViews();
+ if (views.length > 0)
+ {
+ for (CDOView view : views)
+ {
+ long viewTimeoutMillis = timeoutMillis == NO_TIMEOUT ? NO_TIMEOUT : end - System.currentTimeMillis();
+ boolean ok = view.waitForUpdate(updateTime, viewTimeoutMillis);
+ if (!ok)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // Session without views
+ for (;;)
+ {
+ synchronized (lastUpdateTimeLock)
+ {
+ if (lastUpdateTime >= updateTime)
+ {
+ return true;
+ }
+
+ long now = System.currentTimeMillis();
+ if (now >= end)
+ {
+ return false;
+ }
+
+ try
+ {
+ lastUpdateTimeLock.wait(end - now);
+ }
+ catch (InterruptedException ex)
+ {
+ throw WrappedException.wrap(ex);
+ }
+ }
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ public Object resolveElementProxy(CDORevision revision, EStructuralFeature feature, int accessIndex, int serverIndex)
+ {
+ CDOCollectionLoadingPolicy policy = options().getCollectionLoadingPolicy();
+ return policy.resolveProxy(revision, feature, accessIndex, serverIndex);
+ }
+
+ /**
+ * @since 4.0
+ */
+ public void resolveAllElementProxies(CDORevision revision)
+ {
+ CDOCollectionLoadingPolicy policy = options().getCollectionLoadingPolicy();
+ for (EStructuralFeature feature : revision.getEClass().getEAllStructuralFeatures())
+ {
+ if (feature instanceof EReference)
+ {
+ EReference reference = (EReference)feature;
+ if (reference.isMany() && EMFUtil.isPersistent(reference))
+ {
+ CDOList list = ((InternalCDORevision)revision).getList(reference);
+ for (Iterator<Object> it = list.iterator(); it.hasNext();)
+ {
+ Object element = it.next();
+ if (element instanceof CDOElementProxy)
+ {
+ policy.resolveAllProxies(revision, reference);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void handleRepositoryTypeChanged(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType)
+ {
+ fireEvent(new RepositoryTypeChangedEvent(this, oldType, newType));
+ }
+
+ public void handleRepositoryStateChanged(CDOCommonRepository.State oldState, CDOCommonRepository.State newState)
+ {
+ fireEvent(new RepositoryStateChangedEvent(this, oldState, newState));
+ }
+
+ public void handleBranchNotification(InternalCDOBranch branch)
+ {
+ getBranchManager().handleBranchCreated(branch);
+ }
+
+ public void handleCommitNotification(CDOCommitInfo commitInfo)
+ {
+ try
+ {
+ registerPackageUnits(commitInfo.getNewPackageUnits());
+ invalidate(commitInfo, null);
+ }
+ catch (RuntimeException ex)
+ {
+ if (isActive())
+ {
+ OM.LOG.error(ex);
+ }
+ else
+ {
+ OM.LOG.info(Messages.getString("CDOSessionImpl.2")); //$NON-NLS-1$
+ }
+ }
+ }
+
+ public void handleLockNotification(CDOLockChangeInfo lockChangeInfo, InternalCDOView sender)
+ {
+ for (InternalCDOView view : getViews())
+ {
+ if (view != sender)
+ {
+ view.handleLockNotification(sender, lockChangeInfo);
+ }
+ }
+
+ fireEvent(new LocksChangedEvent(sender, lockChangeInfo));
+ }
+
+ private void registerPackageUnits(List<CDOPackageUnit> packageUnits)
+ {
+ InternalCDOPackageRegistry packageRegistry = getPackageRegistry();
+ for (CDOPackageUnit newPackageUnit : packageUnits)
+ {
+ packageRegistry.putPackageUnit((InternalCDOPackageUnit)newPackageUnit);
+ }
+ }
+
+ private Map<CDOID, InternalCDORevision> reviseRevisions(CDOCommitInfo commitInfo)
+ {
+ Map<CDOID, InternalCDORevision> oldRevisions = null;
+ CDOBranch newBranch = commitInfo.getBranch();
+ long timeStamp = commitInfo.getTimeStamp();
+ InternalCDORevisionManager revisionManager = getRevisionManager();
+
+ // Cache new revisions
+ for (CDOIDAndVersion key : commitInfo.getNewObjects())
+ {
+ if (key instanceof InternalCDORevision)
+ {
+ InternalCDORevision newRevision = (InternalCDORevision)key;
+ revisionManager.addRevision(newRevision);
+ }
+ }
+
+ // Apply deltas and cache the resulting new revisions, if possible...
+ for (CDORevisionKey key : commitInfo.getChangedObjects())
+ {
+ // Add old values to revision deltas.
+ if (key instanceof CDORevisionDelta)
+ {
+ final CDORevisionDelta revisionDelta = (CDORevisionDelta)key;
+ final CDORevision oldRevision = revisionManager.getRevisionByVersion(revisionDelta.getID(), revisionDelta,
+ CDORevision.UNCHUNKED, false);
+
+ if (oldRevision != null)
+ {
+ CDOFeatureDeltaVisitor visitor = new CDOFeatureDeltaVisitorImpl()
+ {
+ private List<Object> workList;
+
+ @Override
+ public void visit(CDOAddFeatureDelta delta)
+ {
+ workList.add(delta.getIndex(), delta.getValue());
+ }
+
+ @Override
+ public void visit(CDOClearFeatureDelta delta)
+ {
+ workList.clear();
+ }
+
+ @Override
+ public void visit(CDOListFeatureDelta deltas)
+ {
+ @SuppressWarnings("unchecked")
+ List<Object> list = (List<Object>)((InternalCDORevision)oldRevision).getValue(deltas.getFeature());
+ if (list != null)
+ {
+ workList = new ArrayList<Object>(list);
+ super.visit(deltas);
+ }
+ }
+
+ @Override
+ public void visit(CDOMoveFeatureDelta delta)
+ {
+ Object value = workList.get(delta.getOldPosition());
+ ((CDOMoveFeatureDeltaImpl)delta).setValue(value);
+ ECollections.move(workList, delta.getNewPosition(), delta.getOldPosition());
+ }
+
+ @Override
+ public void visit(CDORemoveFeatureDelta delta)
+ {
+ Object oldValue = workList.remove(delta.getIndex());
+ ((CDOSingleValueFeatureDeltaImpl)delta).setValue(oldValue);
+ }
+
+ @Override
+ public void visit(CDOSetFeatureDelta delta)
+ {
+ EStructuralFeature feature = delta.getFeature();
+ Object value = null;
+ if (feature.isMany())
+ {
+ value = workList.set(delta.getIndex(), delta.getValue());
+ }
+ else
+ {
+ value = ((InternalCDORevision)oldRevision).getValue(feature);
+ }
+
+ ((CDOSetFeatureDeltaImpl)delta).setOldValue(value);
+ }
+ };
+
+ for (CDOFeatureDelta featureDelta : revisionDelta.getFeatureDeltas())
+ {
+ featureDelta.accept(visitor);
+ }
+ }
+ }
+
+ CDOID id = key.getID();
+ Pair<InternalCDORevision, InternalCDORevision> pair = createNewRevision(key, commitInfo);
+ if (pair != null)
+ {
+ InternalCDORevision newRevision = pair.getElement2();
+ revisionManager.addRevision(newRevision);
+ if (oldRevisions == null)
+ {
+ oldRevisions = new HashMap<CDOID, InternalCDORevision>();
+ }
+
+ InternalCDORevision oldRevision = pair.getElement1();
+ oldRevisions.put(id, oldRevision);
+ }
+ else
+ {
+ // ... otherwise try to revise old revision if it is in the same branch
+ if (ObjectUtil.equals(key.getBranch(), newBranch))
+ {
+ revisionManager.reviseVersion(id, key, timeStamp);
+ }
+ }
+ }
+
+ // Revise old revisions
+ for (CDOIDAndVersion key : commitInfo.getDetachedObjects())
+ {
+ CDOID id = key.getID();
+ int version = key.getVersion();
+ if (version == CDOBranchVersion.UNSPECIFIED_VERSION)
+ {
+ revisionManager.reviseLatest(id, newBranch);
+ }
+ else
+ {
+ CDOBranchVersion branchVersion = newBranch.getVersion(version);
+ revisionManager.reviseVersion(id, branchVersion, timeStamp);
+ }
+ }
+
+ return oldRevisions;
+ }
+
+ private Pair<InternalCDORevision, InternalCDORevision> createNewRevision(CDORevisionKey potentialDelta,
+ CDOCommitInfo commitInfo)
+ {
+ if (potentialDelta instanceof CDORevisionDelta)
+ {
+ CDORevisionDelta delta = (CDORevisionDelta)potentialDelta;
+ CDOID id = delta.getID();
+
+ InternalCDORevisionManager revisionManager = getRevisionManager();
+ InternalCDORevision oldRevision = revisionManager.getRevisionByVersion(id, potentialDelta, CDORevision.UNCHUNKED,
+ false);
+ if (oldRevision != null)
+ {
+ InternalCDORevision newRevision = oldRevision.copy();
+ newRevision.adjustForCommit(commitInfo.getBranch(), commitInfo.getTimeStamp());
+
+ CDORevisable target = delta.getTarget();
+ if (target != null)
+ {
+ newRevision.setVersion(target.getVersion());
+ }
+
+ delta.apply(newRevision);
+ newRevision.freeze();
+ return new Pair<InternalCDORevision, InternalCDORevision>(oldRevision, newRevision);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender)
+ {
+ long previousTimeStamp = commitInfo.getPreviousTimeStamp();
+ long lastUpdateTime = getLastUpdateTime();
+
+ if (previousTimeStamp < lastUpdateTime)
+ {
+ previousTimeStamp = lastUpdateTime;
+ }
+
+ synchronized (outOfSequenceInvalidations)
+ {
+ outOfSequenceInvalidations.put(previousTimeStamp, new Pair<CDOCommitInfo, InternalCDOTransaction>(commitInfo,
+ sender));
+ }
+
+ long nextPreviousTimeStamp = lastUpdateTime;
+ for (;;)
+ {
+ synchronized (outOfSequenceInvalidations)
+ {
+ Pair<CDOCommitInfo, InternalCDOTransaction> currentPair = outOfSequenceInvalidations
+ .remove(nextPreviousTimeStamp);
+
+ // If we don't have the invalidation that follows the last one we processed,
+ // then there is nothing we can do right now
+ if (currentPair == null)
+ {
+ break;
+ }
+
+ final CDOCommitInfo currentCommitInfo = currentPair.getElement1();
+ final InternalCDOTransaction currentSender = currentPair.getElement2();
+ nextPreviousTimeStamp = currentCommitInfo.getTimeStamp();
+
+ if (sender == null)
+ {
+ QueueRunner invalidationRunner = getInvalidationRunner();
+ invalidationRunner.addWork(new Runnable()
+ {
+ public void run()
+ {
+ invalidateOrdered(currentCommitInfo, currentSender);
+ }
+ });
+ }
+ else
+ {
+ invalidateOrdered(currentCommitInfo, currentSender);
+ }
+ }
+ }
+ }
+
+ /**
+ * This method is synchronized on outOfSequenceInvalidations by the caller!
+ */
+ private QueueRunner getInvalidationRunner()
+ {
+ if (invalidationRunner == null)
+ {
+ invalidationRunner = new QueueRunner();
+ invalidationRunner.activate();
+ }
+
+ return invalidationRunner;
+ }
+
+ private void invalidateOrdered(CDOCommitInfo commitInfo, InternalCDOTransaction sender)
+ {
+ Map<CDOID, InternalCDORevision> oldRevisions = null;
+ boolean success = commitInfo.getBranch() != null;
+ if (success)
+ {
+ oldRevisions = reviseRevisions(commitInfo);
+ }
+
+ if (options.isPassiveUpdateEnabled())
+ {
+ setLastUpdateTime(commitInfo.getTimeStamp());
+ }
+
+ if (success)
+ {
+ fireInvalidationEvent(sender, commitInfo);
+ }
+
+ for (InternalCDOView view : getViews())
+ {
+ if (view != sender)
+ {
+ invalidateView(commitInfo, view, oldRevisions);
+ }
+ else
+ {
+ view.setLastUpdateTime(commitInfo.getTimeStamp());
+ }
+ }
+ }
+
+ private void invalidateView(CDOCommitInfo commitInfo, InternalCDOView view,
+ Map<CDOID, InternalCDORevision> oldRevisions)
+ {
+ try
+ {
+ CDOBranch branch = commitInfo.getBranch();
+ long lastUpdateTime = commitInfo.getTimeStamp();
+ List<CDORevisionKey> allChangedObjects = commitInfo.getChangedObjects();
+ List<CDOIDAndVersion> allDetachedObjects = commitInfo.getDetachedObjects();
+ view.invalidate(branch, lastUpdateTime, allChangedObjects, allDetachedObjects, oldRevisions, true);
+ }
+ catch (RuntimeException ex)
+ {
+ if (view.isActive())
+ {
+ OM.LOG.error(ex);
+ }
+ else
+ {
+ OM.LOG.info(Messages.getString("CDOSessionImpl.1")); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void fireInvalidationEvent(InternalCDOTransaction sender, CDOCommitInfo commitInfo)
+ {
+ fireEvent(new InvalidationEvent(sender, commitInfo));
+ }
+
+ @Override
+ public String toString()
+ {
+ String name = repositoryInfo == null ? "?" : repositoryInfo.getName(); //$NON-NLS-1$
+ return MessageFormat.format("Session{0} [{1}]", sessionID, name); //$NON-NLS-1$
+ }
+
+ public CDOBranchPoint getCommittedSinceLastRefresh(CDOID id)
+ {
+ if (isSticky())
+ {
+ return committedSinceLastRefresh.get(id);
+ }
+
+ return null;
+ }
+
+ public void setCommittedSinceLastRefresh(CDOID id, CDOBranchPoint branchPoint)
+ {
+ if (isSticky())
+ {
+ committedSinceLastRefresh.put(id, branchPoint);
+ }
+ }
+
+ public void clearCommittedSinceLastRefresh()
+ {
+ if (isSticky())
+ {
+ committedSinceLastRefresh.clear();
+ }
+ }
+
+ public boolean isSticky()
+ {
+ return !options().isPassiveUpdateEnabled() && getRepositoryInfo().isSupportingAudits();
+ }
+
+ public CDOChangeSetData compareRevisions(CDOBranchPoint source, CDOBranchPoint target)
+ {
+ long now = getLastUpdateTime();
+
+ if (target.getTimeStamp() == CDOBranchPoint.UNSPECIFIED_DATE)
+ {
+ target = target.getBranch().getPoint(now);
+ }
+
+ if (source.getTimeStamp() == CDOBranchPoint.UNSPECIFIED_DATE)
+ {
+ source = source.getBranch().getPoint(now);
+ }
+
+ CDORevisionAvailabilityInfo targetInfo = createRevisionAvailabilityInfo(target);
+ CDORevisionAvailabilityInfo sourceInfo = createRevisionAvailabilityInfo(source);
+
+ Set<CDOID> ids = sessionProtocol.loadMergeData(targetInfo, sourceInfo, null, null);
+
+ cacheRevisions(targetInfo);
+ cacheRevisions(sourceInfo);
+
+ return CDORevisionUtil.createChangeSetData(ids, sourceInfo, targetInfo);
+ }
+
+ public CDORevisionAvailabilityInfo createRevisionAvailabilityInfo(CDOBranchPoint branchPoint)
+ {
+ CDORevisionAvailabilityInfo info = new CDORevisionAvailabilityInfo(branchPoint);
+
+ InternalCDORevisionManager revisionManager = getRevisionManager();
+ InternalCDORevisionCache cache = revisionManager.getCache();
+
+ List<CDORevision> revisions = cache.getRevisions(branchPoint);
+ for (CDORevision revision : revisions)
+ {
+ if (revision instanceof PointerCDORevision)
+ {
+ PointerCDORevision pointer = (PointerCDORevision)revision;
+ CDOBranchVersion target = pointer.getTarget();
+ if (target != null)
+ {
+ revision = cache.getRevisionByVersion(pointer.getID(), target);
+ }
+ }
+ else if (revision instanceof DetachedCDORevision)
+ {
+ revision = null;
+ }
+
+ if (revision != null)
+ {
+ resolveAllElementProxies(revision);
+ info.addRevision(revision);
+ }
+ }
+
+ return info;
+ }
+
+ public void cacheRevisions(CDORevisionAvailabilityInfo info)
+ {
+ InternalCDORevisionManager revisionManager = getRevisionManager();
+ CDOBranch branch = info.getBranchPoint().getBranch();
+ for (CDORevisionKey key : info.getAvailableRevisions().values())
+ {
+ CDORevision revision = (CDORevision)key;
+ revisionManager.addRevision(revision);
+
+ if (!ObjectUtil.equals(revision.getBranch(), branch))
+ {
+ CDOID id = revision.getID();
+ CDORevision firstRevision = revisionManager.getCache().getRevisionByVersion(id,
+ branch.getVersion(CDOBranchVersion.FIRST_VERSION));
+ if (firstRevision != null)
+ {
+ long revised = firstRevision.getTimeStamp() - 1L;
+ CDOBranchVersion target = CDOBranchUtil.copyBranchVersion(revision);
+ PointerCDORevision pointer = new PointerCDORevision(revision.getEClass(), id, branch, revised, target);
+ revisionManager.addRevision(pointer);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void doActivate() throws Exception
+ {
+ super.doActivate();
+
+ InternalCDORemoteSessionManager remoteSessionManager = new CDORemoteSessionManagerImpl();
+ remoteSessionManager.setLocalSession(this);
+ setRemoteSessionManager(remoteSessionManager);
+ remoteSessionManager.activate();
+
+ checkState(sessionProtocol, "sessionProtocol"); //$NON-NLS-1$
+ checkState(remoteSessionManager, "remoteSessionManager"); //$NON-NLS-1$
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ super.doDeactivate();
+
+ LifecycleUtil.deactivate(invalidationRunner);
+ outOfSequenceInvalidations.clear();
+
+ unhookSessionProtocol();
+
+ CDORemoteSessionManager remoteSessionManager = getRemoteSessionManager();
+ setRemoteSessionManager(null);
+ LifecycleUtil.deactivate(remoteSessionManager);
+
+ CDOSessionProtocol sessionProtocol = getSessionProtocol();
+ LifecycleUtil.deactivate(sessionProtocol);
+ setSessionProtocol(null);
+ }
+
+ /**
+ * Makes this session start listening to its protocol
+ */
+ protected CDOSessionProtocol hookSessionProtocol()
+ {
+ EventUtil.addListener(sessionProtocol, sessionProtocolListener);
+ return sessionProtocol;
+ }
+
+ /**
+ * Makes this session stop listening to its protocol
+ */
+ protected void unhookSessionProtocol()
+ {
+ EventUtil.removeListener(sessionProtocol, sessionProtocolListener);
+ }
+
+ protected void sessionProtocolDeactivated()
+ {
+ deactivate();
+ }
+
+ /**
+ * A separate class for better monitor debugging.
+ *
+ * @author Eike Stepper
+ */
+ private static final class LastUpdateTimeLock
+ {
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class OutOfSequenceInvalidations extends
+ HashMap<Long, Pair<CDOCommitInfo, InternalCDOTransaction>>
+ {
+ private static final long serialVersionUID = 1L;
+ }
+
+ /**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+ protected class OptionsImpl extends Notifier implements Options
+ {
+ private boolean generatedPackageEmulationEnabled;
+
+ private boolean passiveUpdateEnabled = true;
+
+ private PassiveUpdateMode passiveUpdateMode = PassiveUpdateMode.INVALIDATIONS;
+
+ private LockNotificationMode lockNotificationMode = LockNotificationMode.IF_REQUIRED_BY_VIEWS;
+
+ private CDOCollectionLoadingPolicy collectionLoadingPolicy;
+
+ private CDOLobStore lobCache = CDOLobStoreImpl.INSTANCE;
+
+ public OptionsImpl()
+ {
+ setCollectionLoadingPolicy(null); // Init default
+ }
+
+ public CDOSession getContainer()
+ {
+ return CDOSessionImpl.this;
+ }
+
+ public boolean isGeneratedPackageEmulationEnabled()
+ {
+ return generatedPackageEmulationEnabled;
+ }
+
+ public synchronized void setGeneratedPackageEmulationEnabled(boolean generatedPackageEmulationEnabled)
+ {
+ this.generatedPackageEmulationEnabled = generatedPackageEmulationEnabled;
+ if (this.generatedPackageEmulationEnabled != generatedPackageEmulationEnabled)
+ {
+ this.generatedPackageEmulationEnabled = generatedPackageEmulationEnabled;
+ // TODO Check inconsistent state if switching off?
+
+ IListener[] listeners = getListeners();
+ if (listeners != null)
+ {
+ fireEvent(new GeneratedPackageEmulationEventImpl(), listeners);
+ }
+ }
+ }
+
+ public boolean isPassiveUpdateEnabled()
+ {
+ return passiveUpdateEnabled;
+ }
+
+ public synchronized void setPassiveUpdateEnabled(boolean passiveUpdateEnabled)
+ {
+ if (this.passiveUpdateEnabled != passiveUpdateEnabled)
+ {
+ this.passiveUpdateEnabled = passiveUpdateEnabled;
+ CDOSessionProtocol protocol = getSessionProtocol();
+ if (protocol != null)
+ {
+ if (passiveUpdateEnabled)
+ {
+ refresh(true);
+ }
+ else
+ {
+ protocol.disablePassiveUpdate();
+ }
+
+ IListener[] listeners = getListeners();
+ if (listeners != null)
+ {
+ fireEvent(new PassiveUpdateEventImpl(!passiveUpdateEnabled, passiveUpdateEnabled, passiveUpdateMode,
+ passiveUpdateMode), listeners);
+ }
+ }
+ }
+ }
+
+ public PassiveUpdateMode getPassiveUpdateMode()
+ {
+ return passiveUpdateMode;
+ }
+
+ public void setPassiveUpdateMode(PassiveUpdateMode passiveUpdateMode)
+ {
+ checkArg(passiveUpdateMode, "passiveUpdateMode"); //$NON-NLS-1$
+ if (this.passiveUpdateMode != passiveUpdateMode)
+ {
+ PassiveUpdateMode oldMode = this.passiveUpdateMode;
+ this.passiveUpdateMode = passiveUpdateMode;
+ CDOSessionProtocol protocol = getSessionProtocol();
+ if (protocol != null)
+ {
+ protocol.setPassiveUpdateMode(passiveUpdateMode);
+
+ IListener[] listeners = getListeners();
+ if (listeners != null)
+ {
+ fireEvent(
+ new PassiveUpdateEventImpl(passiveUpdateEnabled, passiveUpdateEnabled, oldMode, passiveUpdateMode),
+ listeners);
+ }
+ }
+ }
+ }
+
+ public LockNotificationMode getLockNotificationMode()
+ {
+ return lockNotificationMode;
+ }
+
+ public void setLockNotificationMode(LockNotificationMode lockNotificationMode)
+ {
+ checkArg(lockNotificationMode, "lockNotificationMode"); //$NON-NLS-1$
+ if (this.lockNotificationMode != lockNotificationMode)
+ {
+ LockNotificationMode oldMode = this.lockNotificationMode;
+ this.lockNotificationMode = lockNotificationMode;
+ CDOSessionProtocol protocol = getSessionProtocol();
+ if (protocol != null)
+ {
+ protocol.setLockNotificationMode(lockNotificationMode);
+
+ IListener[] listeners = getListeners();
+ if (listeners != null)
+ {
+ fireEvent(new LockNotificationModeEventImpl(oldMode, lockNotificationMode), listeners);
+ }
+ }
+ }
+ this.lockNotificationMode = lockNotificationMode;
+ }
+
+ public CDOCollectionLoadingPolicy getCollectionLoadingPolicy()
+ {
+ synchronized (this)
+ {
+ return collectionLoadingPolicy;
+ }
+ }
+
+ public void setCollectionLoadingPolicy(CDOCollectionLoadingPolicy policy)
+ {
+ if (policy == null)
+ {
+ policy = CDOUtil.createCollectionLoadingPolicy(CDORevision.UNCHUNKED, CDORevision.UNCHUNKED);
+ }
+
+ CDOSession oldSession = policy.getSession();
+ if (oldSession != null)
+ {
+ throw new IllegalArgumentException("Policy is already associated with " + oldSession);
+ }
+
+ policy.setSession(CDOSessionImpl.this);
+
+ IListener[] listeners = getListeners();
+ IEvent event = null;
+
+ synchronized (this)
+ {
+ if (collectionLoadingPolicy != policy)
+ {
+ collectionLoadingPolicy = policy;
+ if (listeners != null)
+ {
+ event = new CollectionLoadingPolicyEventImpl();
+ }
+ }
+ }
+
+ if (event != null)
+ {
+ fireEvent(event, listeners);
+ }
+ }
+
+ public CDOLobStore getLobCache()
+ {
+ synchronized (this)
+ {
+ return lobCache;
+ }
+ }
+
+ public void setLobCache(CDOLobStore cache)
+ {
+ if (cache == null)
+ {
+ cache = CDOLobStoreImpl.INSTANCE;
+ }
+
+ IListener[] listeners = getListeners();
+ IEvent event = null;
+
+ synchronized (this)
+ {
+ if (lobCache != cache)
+ {
+ lobCache = cache;
+ if (listeners != null)
+ {
+ event = new LobCacheEventImpl();
+ }
+ }
+ }
+
+ if (event != null)
+ {
+ fireEvent(event, listeners);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private final class GeneratedPackageEmulationEventImpl extends OptionsEvent implements
+ GeneratedPackageEmulationEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ public GeneratedPackageEmulationEventImpl()
+ {
+ super(OptionsImpl.this);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private final class PassiveUpdateEventImpl extends OptionsEvent implements PassiveUpdateEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ private boolean oldEnabled;
+
+ private boolean newEnabled;
+
+ private PassiveUpdateMode oldMode;
+
+ private PassiveUpdateMode newMode;
+
+ public PassiveUpdateEventImpl(boolean oldEnabled, boolean newEnabled, PassiveUpdateMode oldMode,
+ PassiveUpdateMode newMode)
+ {
+ super(OptionsImpl.this);
+ this.oldEnabled = oldEnabled;
+ this.newEnabled = newEnabled;
+ this.oldMode = oldMode;
+ this.newMode = newMode;
+ }
+
+ public boolean getOldEnabled()
+ {
+ return oldEnabled;
+ }
+
+ public boolean getNewEnabled()
+ {
+ return newEnabled;
+ }
+
+ public PassiveUpdateMode getOldMode()
+ {
+ return oldMode;
+ }
+
+ public PassiveUpdateMode getNewMode()
+ {
+ return newMode;
+ }
+ }
+
+ /**
+ * @author Caspar De Groot
+ */
+ private final class LockNotificationModeEventImpl extends OptionsEvent implements LockNotificationModeEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ private LockNotificationMode oldMode, newMode;
+
+ public LockNotificationModeEventImpl(LockNotificationMode oldMode, LockNotificationMode newMode)
+ {
+ super(OptionsImpl.this);
+ this.oldMode = oldMode;
+ this.newMode = newMode;
+ }
+
+ public LockNotificationMode getOldMode()
+ {
+ return oldMode;
+ }
+
+ public LockNotificationMode getNewMode()
+ {
+ return newMode;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private final class CollectionLoadingPolicyEventImpl extends OptionsEvent implements CollectionLoadingPolicyEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ public CollectionLoadingPolicyEventImpl()
+ {
+ super(OptionsImpl.this);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private final class LobCacheEventImpl extends OptionsEvent implements LobCacheEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ public LobCacheEventImpl()
+ {
+ super(OptionsImpl.this);
+ }
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private final class InvalidationEvent extends Event implements CDOSessionInvalidationEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ private InternalCDOTransaction sender;
+
+ private CDOCommitInfo commitInfo;
+
+ public InvalidationEvent(InternalCDOTransaction sender, CDOCommitInfo commitInfo)
+ {
+ super(CDOSessionImpl.this);
+ this.sender = sender;
+ this.commitInfo = commitInfo;
+ }
+
+ @Override
+ public CDOSession getSource()
+ {
+ return (CDOSession)super.getSource();
+ }
+
+ public CDOCommitInfoManager getCommitInfoManager()
+ {
+ return commitInfo.getCommitInfoManager();
+ }
+
+ public CDOTransaction getLocalTransaction()
+ {
+ return sender;
+ }
+
+ @Deprecated
+ public InternalCDOView getView()
+ {
+ return sender;
+ }
+
+ public boolean isRemote()
+ {
+ return sender == null;
+ }
+
+ public CDOBranch getBranch()
+ {
+ return commitInfo.getBranch();
+ }
+
+ public long getTimeStamp()
+ {
+ return commitInfo.getTimeStamp();
+ }
+
+ public long getPreviousTimeStamp()
+ {
+ return commitInfo.getPreviousTimeStamp();
+ }
+
+ public String getUserID()
+ {
+ return commitInfo.getUserID();
+ }
+
+ public String getComment()
+ {
+ return commitInfo.getComment();
+ }
+
+ public boolean isEmpty()
+ {
+ return false;
+ }
+
+ public CDOChangeSetData copy()
+ {
+ return commitInfo.copy();
+ }
+
+ public void merge(CDOChangeSetData changeSetData)
+ {
+ commitInfo.merge(changeSetData);
+ }
+
+ public List<CDOPackageUnit> getNewPackageUnits()
+ {
+ return commitInfo.getNewPackageUnits();
+ }
+
+ public List<CDOIDAndVersion> getNewObjects()
+ {
+ return commitInfo.getNewObjects();
+ }
+
+ public List<CDORevisionKey> getChangedObjects()
+ {
+ return commitInfo.getChangedObjects();
+ }
+
+ public List<CDOIDAndVersion> getDetachedObjects()
+ {
+ return commitInfo.getDetachedObjects();
+ }
+
+ public Map<CDOID, CDOChangeKind> getChangeKinds()
+ {
+ return commitInfo.getChangeKinds();
+ }
+
+ public CDOChangeKind getChangeKind(CDOID id)
+ {
+ return commitInfo.getChangeKind(id);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "CDOSessionInvalidationEvent[" + commitInfo + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ /**
+ * @author Caspar De Groot
+ * @since 4.1
+ */
+ private final class LocksChangedEvent extends DefaultLocksChangedEvent implements CDOSessionLocksChangedEvent
+ {
+ private static final long serialVersionUID = 1L;
+
+ public LocksChangedEvent(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo)
+ {
+ super(CDOSessionImpl.this, sender, lockChangeInfo);
+ }
+
+ @Override
+ public CDOSession getSource()
+ {
+ return (CDOSession)super.getSource();
+ }
+ }
+}
|