diff options
author | Eike Stepper | 2012-05-01 15:45:31 +0000 |
---|---|---|
committer | Eike Stepper | 2012-05-01 15:45:31 +0000 |
commit | 5b576d6563e340f01b169e608f5e0596202a1230 (patch) | |
tree | aaf1b02c3463dcbedd55212dc82a34bfa86528a5 | |
parent | b4d78150e6b5b2277fa70ee3df3ccc1c2e6d2b48 (diff) | |
download | cdo-5b576d6563e340f01b169e608f5e0596202a1230.tar.gz cdo-5b576d6563e340f01b169e608f5e0596202a1230.tar.xz cdo-5b576d6563e340f01b169e608f5e0596202a1230.zip |
[369646] [DB] ClassCastException after setBranch when server cache contains partially loaded collections
https://bugs.eclipse.org/bugs/show_bug.cgi?id=369646
14 files changed, 8317 insertions, 7984 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 24124dcb4d..a5265ea4b0 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,553 +1,552 @@ -/*
- * 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;
- }
- }
-}
+/* + * 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; + } + } +} 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 2608cd2f68..7ad3215886 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,7 +65,6 @@ 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); @@ -78,9 +77,11 @@ 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 PERMISSION_MASK = 0x03; + private static final byte UNCHUNKED_FLAG = 0x08; private CDOID id; @@ -145,13 +146,13 @@ public abstract class BaseCDORevision extends AbstractCDORevision readSystemValues(in); - byte permissionBits = (byte)(in.readByte() & PERMISSION_MASK); - if (permissionBits != CDOPermission.NONE.ordinal()) + byte flagBits = (byte)(in.readByte() & ~FROZEN_FLAG); + if ((flagBits & PERMISSION_MASK) != CDOPermission.NONE.ordinal()) { readValues(in); } - flags = permissionBits; + flags = flagBits; if (READING.isEnabled()) { @@ -203,7 +204,7 @@ public abstract class BaseCDORevision extends AbstractCDORevision CDOPermissionProvider permissionProvider = out.getPermissionProvider(); CDOPermission permission = permissionProvider.getPermission(this); - out.writeByte(permission.getBits()); + out.writeByte(permission.getBits() | flags & UNCHUNKED_FLAG); if (permission != CDOPermission.NONE) { @@ -732,6 +733,22 @@ 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 031f06eb0a..f743b2bbb1 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,4 +354,20 @@ 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 9d646837ba..985b397ec4 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,4 +126,14 @@ 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 72ffca1b96..06d958dfd1 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,6 +279,22 @@ 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 2ac02db01c..b3b1ca7d79 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,1124 +1,1117 @@ -/*
- * 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();
- }
- }
-}
+/* + * 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(); + } + } +} 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 d65e8a6b7f..9b899553c1 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,287 +1,542 @@ -/*
- * 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);
- }
-}
+/* + * 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); + } +} 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 669bf76b9d..8347f99acc 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,1966 +1,2000 @@ -/*
- * 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();
- }
- }
-}
+/* + * 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(); + } + } +} 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 2644eae146..a7c41b81e6 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,7 +26,6 @@ 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; @@ -1038,13 +1037,7 @@ public class TransactionCommitContext implements InternalCommitContext } // 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()); - } - } + repository.ensureChunks(oldRevision); 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 55ad08cb15..07bf2e1403 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,319 +1,301 @@ -/*
- * 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;
- }
-}
+/* + * 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; + } +} 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 562881acdb..a3c652424a 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,240 +1,245 @@ -/*
- * 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);
-}
+/* + * 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); +} 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 b9fef3935e..ce4235b5f9 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,1632 +1,1633 @@ -/*
- * 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();
- }
- }
-}
+/* + * 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(); + } + } +} 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 1d93cabcbd..36e51ebf6a 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,6 +331,8 @@ 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 f8541bf747..708f06e23f 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,1849 +1,1859 @@ -/*
- * 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();
- }
- }
-}
+/* + * 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(); + } + } +} |