Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Taal2011-05-15 12:02:14 +0000
committerMartin Taal2011-05-15 12:02:14 +0000
commitafe13e3f1eb9f9e813330d8092e68c91c441713e (patch)
treed8517fba0a662af401990e3071f53cf2deda6e68 /plugins/org.eclipse.emf.cdo.server.hibernate
parentd59b1ee83e32f8723da2bc981d50699aed91623c (diff)
downloadcdo-afe13e3f1eb9f9e813330d8092e68c91c441713e.tar.gz
cdo-afe13e3f1eb9f9e813330d8092e68c91c441713e.tar.xz
cdo-afe13e3f1eb9f9e813330d8092e68c91c441713e.zip
Fixes bugzilla 345840 - [Hibernate] Make loaded revisions unmutable
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.server.hibernate')
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/META-INF/MANIFEST.MF4
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStore.java10
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOMergeEventListener.java36
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOPropertyGetter.java4
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOPropertySetter.java40
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/WrappedHibernateList.java35
6 files changed, 111 insertions, 18 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.server.hibernate/META-INF/MANIFEST.MF
index 2403d8eeda..892d40b513 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/META-INF/MANIFEST.MF
@@ -33,4 +33,6 @@ Import-Package: org.hibernate;version="[3.6.0,4.0.0)",
org.hibernate.tuple.component;version="[3.6.0,4.0.0)",
org.hibernate.tuple.entity;version="[3.6.0,4.0.0)",
org.hibernate.type;version="[3.6.0,4.0.0)",
- org.hibernate.usertype;version="[3.6.0,4.0.0)"
+ org.hibernate.usertype;version="[3.6.0,4.0.0)",
+ org.hibernate.event;version="[3.6.0,4.0.0)",
+ org.hibernate.event.def;version="[3.6.0,4.0.0)"
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStore.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStore.java
index 790870d263..cf8f45e1ea 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStore.java
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStore.java
@@ -22,6 +22,7 @@ import org.eclipse.emf.cdo.server.hibernate.IHibernateMappingProvider;
import org.eclipse.emf.cdo.server.hibernate.IHibernateStore;
import org.eclipse.emf.cdo.server.internal.hibernate.bundle.OM;
import org.eclipse.emf.cdo.server.internal.hibernate.tuplizer.CDOInterceptor;
+import org.eclipse.emf.cdo.server.internal.hibernate.tuplizer.CDOMergeEventListener;
import org.eclipse.emf.cdo.spi.server.Store;
import org.eclipse.emf.cdo.spi.server.StoreAccessorPool;
@@ -38,6 +39,7 @@ import org.eclipse.emf.ecore.EClass;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
+import org.hibernate.event.MergeEventListener;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.type.StandardBasicTypes;
@@ -105,6 +107,8 @@ public class HibernateStore extends Store implements IHibernateStore
// is initialized on get
private CDOBranchPoint mainBranchHead;
+ private String mappingXml = null;
+
public HibernateStore(IHibernateMappingProvider mappingProvider)
{
this(mappingProvider, null);
@@ -506,7 +510,8 @@ public class HibernateStore extends Store implements IHibernateStore
if (mappingProvider != null)
{
mappingProvider.setHibernateStore(this);
- hibernateConfiguration.addXML(mappingProvider.getMapping());
+ mappingXml = mappingProvider.getMapping();
+ hibernateConfiguration.addXML(mappingXml);
}
if (TRACER.isEnabled())
@@ -518,6 +523,9 @@ public class HibernateStore extends Store implements IHibernateStore
hibernateConfiguration.addInputStream(in);
hibernateConfiguration.setInterceptor(new CDOInterceptor());
+ hibernateConfiguration.getEventListeners().setMergeEventListeners(
+ new MergeEventListener[] { new CDOMergeEventListener() });
+
// make a local copy as it is adapted in the next if-statement
// and we want to keep the original one untouched, if not
// subsequent test runs will fail as they use the same
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOMergeEventListener.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOMergeEventListener.java
new file mode 100644
index 0000000000..34681e1861
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOMergeEventListener.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2004 - 2011 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:
+ * Martin Taal - initial api
+ */
+package org.eclipse.emf.cdo.server.internal.hibernate.tuplizer;
+
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.event.def.DefaultMergeEventListener;
+import org.hibernate.persister.entity.EntityPersister;
+
+import java.util.Map;
+
+/**
+ * The CDOMergeEventListener prevents copying of values of an existing entity to itself.
+ */
+public class CDOMergeEventListener extends DefaultMergeEventListener
+{
+ private static final long serialVersionUID = 1L;
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected void copyValues(final EntityPersister persister, final Object entity, final Object target,
+ final SessionImplementor source, final Map copyCache)
+ {
+ if (entity != target)
+ {
+ super.copyValues(persister, entity, target, source, copyCache);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOPropertyGetter.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOPropertyGetter.java
index 2b0c13b46a..3504f20e38 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOPropertyGetter.java
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOPropertyGetter.java
@@ -90,12 +90,12 @@ public class CDOPropertyGetter extends CDOPropertyHandler implements Getter
}
else
{
- return getEStructuralFeature().getDefaultValue();
+ return null;
}
}
// hibernate sees eenums, CDO sees int
- if (isEEnum)
+ if (isEEnum && value != null)
{
if (value instanceof Enumerator)
{
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOPropertySetter.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOPropertySetter.java
index 808d3fdf7a..676ddf030e 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOPropertySetter.java
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOPropertySetter.java
@@ -17,6 +17,7 @@ import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.common.util.Enumerator;
import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EStructuralFeature;
@@ -79,52 +80,69 @@ public class CDOPropertySetter extends CDOPropertyHandler implements Setter
// handle a special case: the byte array.
// hibernate will pass a Byte[] while CDO wants a byte[] (object vs. primitive array)
-
+ final Object newValue;
if (value instanceof Byte[] && convertByteArray)
{
final Byte[] objectArray = (Byte[])value;
- final byte[] newValue = new byte[objectArray.length];
+ final byte[] newByteValue = new byte[objectArray.length];
int i = 0;
for (byte b : objectArray)
{
- newValue[i++] = b;
+ newByteValue[i++] = b;
}
-
- revision.setValue(getEStructuralFeature(), newValue);
+ newValue = newByteValue;
}
else
{
// hibernate sees enums, cdo sees int's
if (value instanceof Enumerator)
{
- revision.setValue(getEStructuralFeature(), ((Enumerator)value).getValue());
+ newValue = ((Enumerator)value).getValue();
}
else if (value instanceof EEnumLiteral)
{
- revision.setValue(getEStructuralFeature(), ((EEnumLiteral)value).getValue());
+ newValue = ((EEnumLiteral)value).getValue();
}
else if (value == null)
{
final Object defaultValue = getEStructuralFeature().getDefaultValue();
if (defaultValue == null)
{
- revision.setValue(getEStructuralFeature(), null);
+ newValue = null;
}
else if (getEStructuralFeature().isUnsettable())
{
- revision.setValue(getEStructuralFeature(), null);
+ newValue = null;
}
else
{
// there was a default value so was explicitly set to null
// otherwise the default value would be in the db
- revision.setValue(getEStructuralFeature(), CDORevisionData.NIL);
+ newValue = CDORevisionData.NIL;
}
}
else
{
- revision.setValue(getEStructuralFeature(), value);
+ newValue = value;
}
}
+ final Object currentValue = revision.getValue(getEStructuralFeature());
+ final boolean notChanged = currentValue == newValue || currentValue == null && newValue == CDORevisionData.NIL
+ || isEenumDefaultValue(value) || currentValue != null && newValue != null && currentValue.equals(newValue);
+ final boolean hasChanged = !notChanged;
+ if (hasChanged)
+ {
+ revision.setValue(getEStructuralFeature(), newValue);
+ }
+ }
+
+ private boolean isEenumDefaultValue(Object value)
+ {
+ if (getEStructuralFeature().getEType() instanceof EEnum)
+ {
+ final Object defaultValue = getEStructuralFeature().getDefaultValue();
+ return defaultValue == value;
+ }
+ return false;
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/WrappedHibernateList.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/WrappedHibernateList.java
index 13696b5b9f..f027631dd4 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/WrappedHibernateList.java
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/WrappedHibernateList.java
@@ -43,17 +43,21 @@ public class WrappedHibernateList implements InternalCDOList
{
private List<Object> delegate;
+ private boolean frozen;
+
public WrappedHibernateList()
{
}
public void move(int newPosition, Object object)
{
+ checkFrozen();
move(newPosition, indexOf(object));
}
public Object move(int targetIndex, int sourceIndex)
{
+ checkFrozen();
int size = size();
if (sourceIndex >= size)
{
@@ -203,26 +207,31 @@ public class WrappedHibernateList implements InternalCDOList
public void add(int index, Object element)
{
+ checkFrozen();
getDelegate().add(index, getCDOID(element));
}
public boolean add(Object o)
{
+ checkFrozen();
return getDelegate().add(getCDOID(o));
}
public boolean addAll(Collection<? extends Object> c)
{
+ checkFrozen();
return getDelegate().addAll(getCDOIDs(c));
}
public boolean addAll(int index, Collection<? extends Object> c)
{
+ checkFrozen();
return getDelegate().addAll(index, getCDOIDs(c));
}
public void clear()
{
+ checkFrozen();
getDelegate().clear();
}
@@ -287,26 +296,29 @@ public class WrappedHibernateList implements InternalCDOList
public ListIterator<Object> listIterator()
{
- return new CDOHibernateListIterator(getDelegate().listIterator());
+ return new CDOHibernateListIterator(this, getDelegate().listIterator());
}
public ListIterator<Object> listIterator(int index)
{
- return new CDOHibernateListIterator(getDelegate().listIterator(index));
+ return new CDOHibernateListIterator(this, getDelegate().listIterator(index));
}
public Object remove(int index)
{
+ checkFrozen();
return getDelegate().remove(index);
}
public boolean remove(Object o)
{
+ checkFrozen();
return getDelegate().remove(getCDOID(o));
}
public boolean removeAll(Collection<?> c)
{
+ checkFrozen();
return getDelegate().removeAll(getCDOIDs(c));
}
@@ -317,6 +329,7 @@ public class WrappedHibernateList implements InternalCDOList
public Object set(int index, Object element)
{
+ checkFrozen();
if (element instanceof CDOID)
{
return getDelegate().set(index, element);
@@ -401,13 +414,18 @@ public class WrappedHibernateList implements InternalCDOList
{
private final ListIterator<Object> delegate;
- public CDOHibernateListIterator(ListIterator<Object> delegate)
+ private final WrappedHibernateList owner;
+
+ public CDOHibernateListIterator(WrappedHibernateList owner, ListIterator<Object> delegate)
{
this.delegate = delegate;
+ this.owner = owner;
}
public void add(Object o)
{
+ owner.checkFrozen();
+
delegate.add(HibernateUtil.getInstance().getCDOID(o));
}
@@ -455,17 +473,28 @@ public class WrappedHibernateList implements InternalCDOList
public void remove()
{
+ owner.checkFrozen();
delegate.remove();
}
public void set(Object o)
{
+ owner.checkFrozen();
delegate.set(HibernateUtil.getInstance().getCDOID(o));
}
}
public void freeze()
{
+ frozen = true;
+ }
+
+ private void checkFrozen()
+ {
+ if (frozen)
+ {
+ throw new IllegalStateException("Cannot modify a frozen list");
+ }
}
public void setWithoutFrozenCheck(int i, Object value)

Back to the top