diff options
author | Eike Stepper | 2013-01-22 08:29:34 +0000 |
---|---|---|
committer | Eike Stepper | 2013-01-22 08:30:18 +0000 |
commit | 00275a1321c9da35e59ec5fd4b81a215f4c2c1fe (patch) | |
tree | 7849ad21584761580aa3eac5c561a1446ef05e1f | |
parent | cc30ef6f6fbcd02de8fea7d1e3efb6dd27cfbbac (diff) | |
download | cdo-00275a1321c9da35e59ec5fd4b81a215f4c2c1fe.tar.gz cdo-00275a1321c9da35e59ec5fd4b81a215f4c2c1fe.tar.xz cdo-00275a1321c9da35e59ec5fd4b81a215f4c2c1fe.zip |
[362270] CDODeltaNotification.getNewValue() returns a CDOIDExternal
instead of the EObject from the containing XMIResource
https://bugs.eclipse.org/bugs/show_bug.cgi?id=362270
4 files changed, 330 insertions, 5 deletions
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_362270b_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_362270b_Test.java new file mode 100644 index 0000000000..5e773280a9 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_362270b_Test.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2004 - 2013 Esteban Dugueperoux 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: + * Esteban Dugueperoux - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.bugzilla; + +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.eresource.CDOResourceFactory; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.model4.ContainedElementNoOpposite; +import org.eclipse.emf.cdo.tests.model4.GenRefMultiContained; +import org.eclipse.emf.cdo.tests.model4.RefSingleNonContainedNPL; +import org.eclipse.emf.cdo.transaction.CDOSavepoint; +import org.eclipse.emf.cdo.transaction.CDOTransaction; + +import org.eclipse.emf.internal.cdo.object.CDOLegacyAdapter; + +import org.eclipse.emf.common.notify.Adapter; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.ECrossReferenceAdapter; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; + +import java.util.Collections; + +/** + * @author Esteban Dugueperoux + */ +public class Bugzilla_362270b_Test extends AbstractCDOTest +{ + private static final String REMOTE_RESOURCE_PATH = "sharedResource.model1"; + + private CDOTransaction cdoTransaction; + + private ContainedElementNoOpposite containedElementNoOpposite1; + + private ContainedElementNoOpposite containedElementNoOpposite2; + + private RefSingleNonContainedNPL refSingleNonContainedNPL1; + + private RefSingleNonContainedNPL refSingleNonContainedNPL2; + + @Override + public void setUp() throws Exception + { + super.setUp(); + + Resource.Factory.Registry registry = Resource.Factory.Registry.INSTANCE; + registry.getProtocolToFactoryMap().put("cdo.net4j.tcp", CDOResourceFactory.INSTANCE); + registry.getExtensionToFactoryMap().put("model1", new XMIResourceFactoryImpl()); + + CDOSession session = openSession(); + cdoTransaction = session.openTransaction(); + init(cdoTransaction); + } + + private void init(CDOTransaction cdoTransaction) throws Exception + { + URI localResourceURI = URI.createFileURI(createTempFile("resource", ".model1").getCanonicalPath()); + Resource remoteResource = cdoTransaction.createResource(getResourcePath(REMOTE_RESOURCE_PATH)); + Resource localResource = cdoTransaction.getResourceSet().createResource(localResourceURI); + + GenRefMultiContained localGenRefMultiContained = getModel4Factory().createGenRefMultiContained(); + containedElementNoOpposite1 = getModel4Factory().createContainedElementNoOpposite(); + containedElementNoOpposite2 = getModel4Factory().createContainedElementNoOpposite(); + localGenRefMultiContained.getElements().add(containedElementNoOpposite1); + localGenRefMultiContained.getElements().add(containedElementNoOpposite2); + + localResource.getContents().add(localGenRefMultiContained); + localResource.save(Collections.emptyMap()); + + GenRefMultiContained genRefMultiContained = getModel4Factory().createGenRefMultiContained(); + refSingleNonContainedNPL1 = getModel4Factory().createRefSingleNonContainedNPL(); + refSingleNonContainedNPL2 = getModel4Factory().createRefSingleNonContainedNPL(); + refSingleNonContainedNPL1.setElement(containedElementNoOpposite1); + refSingleNonContainedNPL2.setElement(containedElementNoOpposite1); + genRefMultiContained.getElements().add(refSingleNonContainedNPL1); + genRefMultiContained.getElements().add(refSingleNonContainedNPL2); + remoteResource.getContents().add(genRefMultiContained); + remoteResource.save(Collections.emptyMap()); + + genRefMultiContained.eAdapters().add(new ECrossReferenceAdapter()); + } + + public void testRollback() throws Exception + { + RemoteUser remoteUser = new RemoteUser(); + remoteUser.accessContents(); + + CDOSavepoint savepoint = cdoTransaction.setSavepoint(); + refSingleNonContainedNPL1.setElement(containedElementNoOpposite2); + refSingleNonContainedNPL1.setElement(containedElementNoOpposite1); + savepoint.rollback(); + refSingleNonContainedNPL2.setElement(containedElementNoOpposite2); + refSingleNonContainedNPL2.setElement(containedElementNoOpposite1); + + cdoTransaction.commit(); + + Adapter adapter = EcoreUtil.getAdapter(containedElementNoOpposite1.eAdapters(), CDOLegacyAdapter.class); + assertNull("A legacy adapter should NOT be attached to an external object", adapter); + } + + /** + * @author Esteban Dugueperoux + */ + private final class RemoteUser + { + private CDOTransaction transaction; + + private CDOResource sharedResource; + + private GenRefMultiContained genRefMultiContained; + + public RemoteUser() + { + CDOSession session = openSession(); + transaction = session.openTransaction(); + sharedResource = transaction.getResource(getResourcePath(REMOTE_RESOURCE_PATH)); + } + + public void accessContents() + { + genRefMultiContained = (GenRefMultiContained)sharedResource.getContents().get(0); + genRefMultiContained.eAdapters().add(new ECrossReferenceAdapter()); + } + } + + @Override + public void tearDown() throws Exception + { + cdoTransaction = null; + containedElementNoOpposite1 = null; + containedElementNoOpposite2 = null; + refSingleNonContainedNPL1 = null; + refSingleNonContainedNPL2 = null; + super.tearDown(); + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_362270c_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_362270c_Test.java new file mode 100644 index 0000000000..4721a53933 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_362270c_Test.java @@ -0,0 +1,157 @@ +package org.eclipse.emf.cdo.tests.bugzilla; + +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.model1.Company; +import org.eclipse.emf.cdo.tests.model1.PurchaseOrder; +import org.eclipse.emf.cdo.tests.model1.Supplier; +import org.eclipse.emf.cdo.transaction.CDOSavepoint; +import org.eclipse.emf.cdo.transaction.CDOTransaction; + +import org.eclipse.emf.internal.cdo.object.CDOLegacyWrapper; + +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.common.notify.impl.AdapterImpl; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; +import org.eclipse.emf.edit.command.AddCommand; +import org.eclipse.emf.edit.command.RemoveCommand; +import org.eclipse.emf.transaction.RecordingCommand; +import org.eclipse.emf.transaction.ResourceSetChangeEvent; +import org.eclipse.emf.transaction.ResourceSetListenerImpl; +import org.eclipse.emf.transaction.RollbackException; +import org.eclipse.emf.transaction.TransactionalEditingDomain; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +import java.io.File; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author Esteban Dugueperoux + */ +public class Bugzilla_362270c_Test extends AbstractCDOTest +{ + private static final String RESOURCE_PATH = "/test1"; + + public void testNotifierNotACDOLegacyAdapter() throws Exception + { + TransactionalEditingDomain domain = TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain(); + ResourceSet resourceSet = domain.getResourceSet(); + + // 1. Create the CDOResource + Company obeoCompany = getModel1Factory().createCompany(); + obeoCompany.setName("OBEO"); + obeoCompany.setCity("Nantes"); + + Supplier martinSupplier = getModel1Factory().createSupplier(); + obeoCompany.getSuppliers().add(martinSupplier); + + CDOSession session = openSession(); + CDOTransaction transaction = session.openTransaction(resourceSet); + CDOResource resource = transaction.createResource(getResourcePath(RESOURCE_PATH)); + + resource.getContents().add(obeoCompany); + resource.save(Collections.emptyMap()); + + // 2. Create the local XMI resource + Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE; + Map<String, Object> m = reg.getExtensionToFactoryMap(); + m.put("model1", new XMIResourceFactoryImpl()); + + Company martinCompany = getModel1Factory().createCompany(); + martinCompany.setName("Martin"); + martinCompany.setCity("Berlin"); + + PurchaseOrder purchaseOrder = getModel1Factory().createPurchaseOrder(); + martinCompany.getPurchaseOrders().add(purchaseOrder); + + File localResourceFile = createTempFile("localResource", ".model1"); + URI localResourceURI = URI.createFileURI(localResourceFile.getAbsolutePath()); + Resource localResource = new ResourceSetImpl().createResource(localResourceURI); + + localResource.getContents().add(martinCompany); + localResource.save(Collections.emptyMap()); + localResource = resourceSet.getResource(localResourceURI, true); + + // 3. Add a reference from the CDOResource to the local resource + Command addPurchaseOrderCmd = AddCommand.create(domain, martinSupplier, getModel1Package() + .getSupplier_PurchaseOrders(), purchaseOrder); + domain.getCommandStack().execute(addPurchaseOrderCmd); + + resource.save(Collections.emptyMap()); + + // 4. Create the first CDOSavepoint + final CDOSavepoint firstSavepoint = transaction.setSavepoint(); + + Rollbacker rollbacker = new Rollbacker(); + domain.addResourceSetListener(rollbacker); + + // 5. Detach a CDOObject + Command removeMartinSupplierCmd = RemoveCommand.create(domain, obeoCompany, getModel1Package() + .getCompany_Suppliers(), martinSupplier); + domain.getCommandStack().execute(removeMartinSupplierCmd); + + // 6. Rollback the previous operation + Command rollbackSavepointCmd = new RecordingCommand(domain) + { + @Override + protected void doExecute() + { + firstSavepoint.rollback(); + } + }; + + NotifierCollector collector = new NotifierCollector(); + martinSupplier.eAdapters().add(collector); + + domain.getCommandStack().execute(rollbackSavepointCmd); + domain.removeResourceSetListener(rollbacker); + + for (Object notifier : collector.getNotifiers()) + { + assertNotInstanceOf(CDOLegacyWrapper.class, notifier); + } + } + + /** + * @author Esteban Dugueperoux + */ + private class Rollbacker extends ResourceSetListenerImpl + { + @Override + public Command transactionAboutToCommit(ResourceSetChangeEvent event) throws RollbackException + { + IStatus status = Status.CANCEL_STATUS; + throw new RollbackException(status); + } + } + + /** + * @author Esteban Dugueperoux + */ + private class NotifierCollector extends AdapterImpl + { + private Set<Object> notifiers = new HashSet<Object>(); + + @Override + public void notifyChanged(Notification msg) + { + notifiers.add(msg.getNotifier()); + } + + public Set<Object> getNotifiers() + { + return notifiers; + } + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDODeltaNotificationImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDODeltaNotificationImpl.java index b79c7f446a..737fddac4c 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDODeltaNotificationImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDODeltaNotificationImpl.java @@ -14,16 +14,19 @@ package org.eclipse.emf.internal.cdo.object; import org.eclipse.emf.cdo.CDODeltaNotification; import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDExternal; import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.cdo.util.ObjectNotFoundException; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.ECollections; +import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.impl.ENotificationImpl; +import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.spi.cdo.InternalCDOObject; import org.eclipse.emf.spi.cdo.InternalCDOView; @@ -136,14 +139,28 @@ public class CDODeltaNotificationImpl extends ENotificationImpl implements CDODe { CDOID id = (CDOID)object; - try + if (id instanceof CDOIDExternal) { - InternalCDOView view = getCDOObject().cdoView(); - object = view.getObject(id, true); + CDOIDExternal idExternal = (CDOIDExternal)id; + Resource resource = notifier.eResource(); + if (resource != null) + { + String uriString = idExternal.getURI(); + URI uri = URI.createURI(uriString); + object = resource.getResourceSet().getEObject(uri, false); + } } - catch (ObjectNotFoundException ex) + else { - object = null; + try + { + InternalCDOView view = getCDOObject().cdoView(); + object = view.getObject(id, true); + } + catch (ObjectNotFoundException ex) + { + object = null; + } } } diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java index 90cbd802ee..291eae1865 100644 --- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java +++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java @@ -524,6 +524,11 @@ public abstract class AbstractOMTest extends TestCase expected.isInstance(object)); } + public static void assertNotInstanceOf(Class<?> expected, Object object) + { + assertEquals("An instance of " + expected + ": " + object.getClass().getName(), false, expected.isInstance(object)); + } + public static void assertActive(Object object) throws InterruptedException { final LatchTimeOuter timeOuter = new LatchTimeOuter(); |