Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Taal2010-11-14 22:40:56 +0000
committerMartin Taal2010-11-14 22:40:56 +0000
commitd838c1011858929372a8f75610681d23ca0d5d1a (patch)
tree34661c4d7aa6221ce7b03ceeafc46576eee0d358 /plugins/org.eclipse.emf.cdo.server.hibernate
parentb06c837fe7a339d1859ca7f27032d1fc83ee87b9 (diff)
downloadcdo-d838c1011858929372a8f75610681d23ca0d5d1a.tar.gz
cdo-d838c1011858929372a8f75610681d23ca0d5d1a.tar.xz
cdo-d838c1011858929372a8f75610681d23ca0d5d1a.zip
Fixes issue [Hibernate] Support queryXRefs
Added support for lob and store property in HibernateStore
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.server.hibernate')
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/mappings/meta.hbm.xml5
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/mappings/resource.hbm.xml8
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernatePackageHandler.java140
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStore.java46
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreAccessor.java178
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreLob.java79
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/SystemProperty.java44
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOBlobUserType.java32
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOClobUserType.java32
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOCustomTypeUserType.java125
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOLobUserType.java150
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDORevisionTuplizer.java19
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/WrappedHibernateList.java13
13 files changed, 848 insertions, 23 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/meta.hbm.xml b/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/meta.hbm.xml
index 1ec5478885..602ac165cf 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/meta.hbm.xml
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/meta.hbm.xml
@@ -41,4 +41,9 @@
</id>
<property name="creationTime"/>
</class>
+
+ <class name="org.eclipse.emf.cdo.server.internal.hibernate.SystemProperty" table="cdo_system_property" lazy="false">
+ <id name="name" type="string" length="255"/>
+ <property name="value" type="text" length="2000"/>
+ </class>
</hibernate-mapping> \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/resource.hbm.xml b/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/resource.hbm.xml
index d95369318c..52c641b113 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/resource.hbm.xml
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/resource.hbm.xml
@@ -69,4 +69,12 @@
</many-to-any>
</list>
</subclass>
+
+ <class name="org.eclipse.emf.cdo.server.internal.hibernate.HibernateStoreLob" table="cdo_lob" lazy="false">
+ <id name="id"/>
+ <property name="clob"/>
+ <property name="blob"/>
+ <property name="size"/>
+ </class>
+
</hibernate-mapping> \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernatePackageHandler.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernatePackageHandler.java
index f03ec07184..2c05244a5d 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernatePackageHandler.java
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernatePackageHandler.java
@@ -12,7 +12,9 @@
package org.eclipse.emf.cdo.server.internal.hibernate;
import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.internal.server.XRefsQueryHandler;
import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;
import org.eclipse.emf.cdo.server.internal.hibernate.bundle.OM;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
@@ -24,7 +26,10 @@ import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.lifecycle.Lifecycle;
import org.eclipse.net4j.util.om.trace.ContextTracer;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.hibernate.Criteria;
@@ -36,10 +41,10 @@ import org.hibernate.cfg.Environment;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.hbm2ddl.SchemaUpdate;
-import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -145,6 +150,8 @@ public class HibernatePackageHandler extends Lifecycle
private boolean doDropSchema;
+ private Map<EClass, Map<EClass, List<EReference>>> sourceCandidates = new HashMap<EClass, Map<EClass, List<EReference>>>();
+
/**
* TODO Necessary to pass/store/dump the properties from the store?
*/
@@ -202,6 +209,7 @@ public class HibernatePackageHandler extends Lifecycle
{
reset();
hibernateStore.reInitialize();
+ sourceCandidates = null;
}
}
@@ -211,6 +219,55 @@ public class HibernatePackageHandler extends Lifecycle
return packageUnits;
}
+ public Map<EClass, List<EReference>> getSourceCandidates(EClass targetEClass)
+ {
+ if (sourceCandidates == null)
+ {
+ computeSourceCandidates();
+ }
+
+ final Map<EClass, List<EReference>> sourceCandidateList = sourceCandidates.get(targetEClass);
+ if (sourceCandidateList == null)
+ {
+ return new HashMap<EClass, List<EReference>>();
+ }
+
+ return sourceCandidateList;
+ }
+
+ private synchronized void computeSourceCandidates()
+ {
+ if (sourceCandidates != null)
+ {
+ return;
+ }
+
+ sourceCandidates = new HashMap<EClass, Map<EClass, List<EReference>>>();
+
+ for (EPackage ePackage : getEPackages())
+ {
+ for (EClassifier eClassifier : ePackage.getEClassifiers())
+ {
+ if (eClassifier instanceof EClass)
+ {
+ sourceCandidates.put((EClass)eClassifier, computeSourceCandidatesByEClass((EClass)eClassifier));
+ }
+ }
+ }
+ }
+
+ private Map<EClass, List<EReference>> computeSourceCandidatesByEClass(EClass targetType)
+ {
+ final Map<EClass, List<EReference>> localSourceCandidates = new HashMap<EClass, List<EReference>>();
+ final Collection<EClass> targetTypes = Collections.singletonList(targetType);
+ for (CDOPackageInfo packageInfo : hibernateStore.getRepository().getPackageRegistry(false).getPackageInfos())
+ {
+ XRefsQueryHandler.collectSourceCandidates(packageInfo, targetTypes, localSourceCandidates);
+ }
+
+ return localSourceCandidates;
+ }
+
public EPackage[] loadPackageUnit(InternalCDOPackageUnit packageUnit)
{
final String nsUri = packageUnit.getTopLevelPackageInfo().getPackageURI();
@@ -388,7 +445,6 @@ public class HibernatePackageHandler extends Lifecycle
session.beginTransaction();
try
{
- System.out.println(new File(".").getAbsolutePath());
final Criteria c = session.createCriteria(SystemInformation.class);
List<?> l = c.list();
int records = l.size();
@@ -399,7 +455,7 @@ public class HibernatePackageHandler extends Lifecycle
systemInformation = new SystemInformation();
systemInformation.setFirstTime(true);
systemInformation.setCreationTime(System.currentTimeMillis());
- session.saveOrUpdate(systemInformation);
+ session.save(systemInformation);
}
else if (records == 1)
{
@@ -420,6 +476,84 @@ public class HibernatePackageHandler extends Lifecycle
}
}
+ Map<String, String> getSystemProperties()
+ {
+ Session session = getSessionFactory().openSession();
+ session.beginTransaction();
+
+ try
+ {
+ final Map<String, String> result = new HashMap<String, String>();
+ final Criteria c = session.createCriteria(SystemProperty.class);
+ for (Object o : c.list())
+ {
+ final SystemProperty systemProperty = (SystemProperty)o;
+ result.put(systemProperty.getName(), systemProperty.getValue());
+ }
+
+ return result;
+ }
+ finally
+ {
+ session.getTransaction().commit();
+ session.close();
+ }
+ }
+
+ void setSystemProperties(Map<String, String> properties)
+ {
+ Session session = getSessionFactory().openSession();
+ session.beginTransaction();
+
+ try
+ {
+ final Map<String, SystemProperty> currentValues = new HashMap<String, SystemProperty>();
+ final Criteria c = session.createCriteria(SystemProperty.class);
+ for (Object o : c.list())
+ {
+ final SystemProperty systemProperty = (SystemProperty)o;
+ currentValues.put(systemProperty.getName(), systemProperty);
+ }
+
+ // update remove currentones
+ final Map<String, String> newValues = new HashMap<String, String>();
+ for (String key : properties.keySet())
+ {
+ if (currentValues.containsKey(key))
+ {
+ final SystemProperty systemProperty = currentValues.get(key);
+ if (properties.get(key) == null)
+ {
+ session.delete(systemProperty);
+ }
+ else
+ {
+ systemProperty.setValue(properties.get(key));
+ session.update(systemProperty);
+ }
+ }
+ else
+ {
+ newValues.put(key, properties.get(key));
+ }
+ }
+
+ // store the new ones
+ for (String key : newValues.keySet())
+ {
+ final SystemProperty systemProperty = new SystemProperty();
+ systemProperty.setName(key);
+ systemProperty.setValue(newValues.get(key));
+ session.save(systemProperty);
+ }
+ }
+ finally
+ {
+ session.getTransaction().commit();
+ session.close();
+ }
+ }
+
protected void initSchema()
{
if (TRACER.isEnabled())
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 cb28be93ce..965bc6a1d2 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
@@ -32,8 +32,10 @@ import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
import org.eclipse.net4j.util.om.log.OMLogger;
import org.eclipse.net4j.util.om.trace.ContextTracer;
+import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EClass;
+import org.hibernate.Hibernate;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
@@ -60,6 +62,10 @@ public class HibernateStore extends Store implements IHibernateStore
{
public static final String TYPE = "hibernate"; //$NON-NLS-1$
+ public static final String ID_TYPE_EANNOTATION_SOURCE = "teneo.cdo";
+
+ public static final String ID_TYPE_EANNOTATION_KEY = "id_type";
+
public static final Set<ObjectType> OBJECT_ID_TYPES = new HashSet<ObjectType>(Arrays.asList(
CDOID.ObjectType.STRING_WITH_CLASSIFIER, CDOID.ObjectType.LONG_WITH_CLASSIFIER));
@@ -300,12 +306,36 @@ public class HibernateStore extends Store implements IHibernateStore
public CDOID createObjectID(String val)
{
- // TODO: implement HibernateStore.createObjectID(val)
- throw new UnsupportedOperationException();
+ final int index = val.lastIndexOf(CDOClassifierRef.URI_SEPARATOR);
+ if (index == -1)
+ {
+ throw new IllegalArgumentException("Id string " + val + " is not a valid id");
+ }
+
+ final String uriPart = val.substring(0, index);
+ final String idPart = val.substring(index + 1);
+ final CDOClassifierRef classifierRef = new CDOClassifierRef(uriPart);
+ final String entityName = getEntityName(classifierRef);
+ final EClass eClass = getEClass(entityName);
+ final EAnnotation typeEAnnotation = eClass.getEAnnotation(ID_TYPE_EANNOTATION_SOURCE);
+ if (typeEAnnotation == null)
+ {
+ throw new IllegalStateException("EClass " + eClass + " does not have a type annotation");
+ }
- // CDOClassifierRef classifierRef = null;
- // Object id = null;
- // return HibernateUtil.getInstance().createCDOID(classifierRef, id);
+ final String idTypeStr = typeEAnnotation.getDetails().get(ID_TYPE_EANNOTATION_KEY);
+ if (Hibernate.STRING.getName().equals(idTypeStr))
+ {
+ return HibernateUtil.getInstance().createCDOID(classifierRef, idPart);
+ }
+ else if (Hibernate.LONG.getName().equals(idTypeStr))
+ {
+ return HibernateUtil.getInstance().createCDOID(classifierRef, new Long(idPart));
+ }
+ else
+ {
+ throw new IllegalArgumentException("ID type " + idTypeStr + " not supported ");
+ }
}
@Override
@@ -322,14 +352,12 @@ public class HibernateStore extends Store implements IHibernateStore
public Map<String, String> getPropertyValues(Set<String> names)
{
- // TODO: implement HibernateStore.getPropertyValues(names)
- throw new UnsupportedOperationException();
+ return packageHandler.getSystemProperties();
}
public void setPropertyValues(Map<String, String> properties)
{
- // TODO: implement HibernateStore.setPropertyValues(properties)
- throw new UnsupportedOperationException();
+ packageHandler.setSystemProperties(properties);
}
public void removePropertyValues(Set<String> names)
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreAccessor.java
index a90b4d144b..e5326a83ec 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreAccessor.java
@@ -35,6 +35,7 @@ import org.eclipse.emf.cdo.server.hibernate.IHibernateStore;
import org.eclipse.emf.cdo.server.hibernate.IHibernateStoreAccessor;
import org.eclipse.emf.cdo.server.internal.hibernate.bundle.OM;
import org.eclipse.emf.cdo.server.internal.hibernate.tuplizer.PersistableListHolder;
+import org.eclipse.emf.cdo.server.internal.hibernate.tuplizer.WrappedHibernateList;
import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
@@ -45,30 +46,42 @@ import org.eclipse.emf.cdo.spi.server.Store;
import org.eclipse.emf.cdo.spi.server.StoreAccessor;
import org.eclipse.emf.cdo.spi.server.StoreChunkReader;
+import org.eclipse.net4j.util.HexUtil;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.io.ExtendedDataInputStream;
+import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.hibernate.Criteria;
import org.hibernate.FlushMode;
+import org.hibernate.Hibernate;
import org.hibernate.Query;
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.io.Reader;
+import java.sql.Clob;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -467,8 +480,54 @@ public class HibernateStoreAccessor extends StoreAccessor implements IHibernateS
public void queryXRefs(QueryXRefsContext context)
{
- // TODO: implement HibernateStoreAccessor.queryXRefs(context)
- throw new UnsupportedOperationException();
+ final Session session = getHibernateSession();
+ for (CDOID targetCdoId : context.getTargetObjects().keySet())
+ {
+ final CDORevision revision = HibernateUtil.getInstance().getCDORevision(targetCdoId);
+ final EClass targetEClass = context.getTargetObjects().get(targetCdoId);
+ final String targetEntityName = getStore().getEntityName(targetEClass);
+ final Map<EClass, List<EReference>> sourceReferences = getStore().getPackageHandler().getSourceCandidates(
+ targetEClass);
+ for (EClass sourceEClass : sourceReferences.keySet())
+ {
+ final String sourceEntityName = getStore().getEntityName(sourceEClass);
+ for (EReference eref : sourceReferences.get(sourceEClass))
+ {
+ final String hql;
+ if (eref.isMany())
+ {
+ hql = "select ref from " + sourceEntityName + " as ref, " + targetEntityName
+ + " as refTo where refTo = :to and refTo in elements(ref." + eref.getName() + ")";
+ }
+ else
+ {
+ hql = "select ref from " + sourceEntityName + " as ref where :to = ref." + eref.getName();
+ }
+
+ final Query qry = session.createQuery(hql);
+ qry.setEntity("to", revision);
+ ScrollableResults result = qry.scroll(ScrollMode.FORWARD_ONLY);
+ while (result.next())
+ {
+ final InternalCDORevision sourceRevision = (InternalCDORevision)result.get()[0];
+ int sourceIndex = 0;
+ if (eref.isMany())
+ {
+ // note this takes performance for sure as the list is read,
+ // consider not supporting sourceIndex, or doing it differently
+ final WrappedHibernateList cdoList = (WrappedHibernateList)sourceRevision.getList(eref);
+ sourceIndex = cdoList.getDelegate().indexOf(revision);
+ }
+
+ boolean more = context.addXRef(targetCdoId, sourceRevision.getID(), eref, sourceIndex);
+ if (!more)
+ {
+ return;
+ }
+ }
+ }
+ }
+ }
}
private CDOID getHibernateID(CDOID id)
@@ -533,6 +592,8 @@ public class HibernateStoreAccessor extends StoreAccessor implements IHibernateS
@Override
public void write(InternalCommitContext context, OMMonitor monitor)
{
+ // NOTE: the same flow is also present in the super class (StoreAccessor)
+
HibernateThreadContext.setCommitContext(context);
if (context.getNewPackageUnits().length > 0)
{
@@ -608,6 +669,36 @@ public class HibernateStoreAccessor extends StoreAccessor implements IHibernateS
repairResourceIDs(repairResourceIDs, session);
session.flush();
+
+ // write the blobs
+ ExtendedDataInputStream in = context.getLobs();
+ if (in != null)
+ {
+ try
+ {
+ int count = in.readInt();
+ for (int i = 0; i < count; i++)
+ {
+ byte[] id = in.readByteArray();
+ long size = in.readLong();
+ if (size > 0)
+ {
+ writeBlob(id, size, in);
+ }
+ else
+ {
+ writeClob(id, -size, new InputStreamReader(in));
+ }
+ }
+ }
+ catch (IOException ex)
+ {
+ throw WrappedException.wrap(ex);
+ }
+ }
+
+ session.flush();
+
}
catch (Exception e)
{
@@ -750,28 +841,95 @@ public class HibernateStoreAccessor extends StoreAccessor implements IHibernateS
public void queryLobs(List<byte[]> ids)
{
- // TODO: implement HibernateStoreAccessor.queryLobs(ids)
- throw new UnsupportedOperationException();
+ for (Iterator<byte[]> it = ids.iterator(); it.hasNext();)
+ {
+ byte[] id = it.next();
+ final HibernateStoreLob lob = getCreateHibernateStoreLob(id);
+ if (lob.isNew())
+ {
+ it.remove();
+ }
+ }
}
public void loadLob(byte[] id, OutputStream out) throws IOException
{
- // TODO: implement HibernateStoreAccessor.loadLob(id, out)
- throw new UnsupportedOperationException();
+ final HibernateStoreLob lob = getCreateHibernateStoreLob(id);
+ // can this ever occur?
+ // TODO: how should non-existence be handled? Currently results in a timeout
+ // on the client.
+ if (lob.isNew())
+ {
+ throw new IllegalStateException("Lob with id " + HexUtil.bytesToHex(id) + " does not exist");
+ }
+
+ final long size = lob.getSize();
+ try
+ {
+ if (lob.getBlob() != null)
+ {
+ InputStream in = lob.getBlob().getBinaryStream();
+ IOUtil.copyBinary(in, out, size);
+ }
+ else
+ {
+ Clob clob = lob.getClob();
+ Reader in = clob.getCharacterStream();
+ IOUtil.copyCharacter(in, new OutputStreamWriter(out), size);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(e);
+ }
}
@Override
protected void writeBlob(byte[] id, long size, InputStream inputStream) throws IOException
{
- // TODO: implement HibernateStoreAccessor.writeBlob(id, size, inputStream)
- throw new UnsupportedOperationException();
+ final HibernateStoreLob lob = getCreateHibernateStoreLob(id);
+ if ((inputStream == null || size == 0) && !lob.isNew())
+ {
+ getHibernateSession().delete(lob);
+ }
+ else
+ {
+ lob.setBlob(Hibernate.createBlob(inputStream, (int)size));
+ lob.setSize((int)size);
+ lob.setClob(null);
+ getHibernateSession().saveOrUpdate(lob);
+ }
}
@Override
protected void writeClob(byte[] id, long size, Reader reader) throws IOException
{
- // TODO: implement HibernateStoreAccessor.writeClob(id, size, reader)
- throw new UnsupportedOperationException();
+ final HibernateStoreLob lob = getCreateHibernateStoreLob(id);
+ if ((reader == null || size == 0) && !lob.isNew())
+ {
+ getHibernateSession().delete(lob);
+ }
+ else
+ {
+ lob.setClob(Hibernate.createClob(reader, (int)size));
+ lob.setSize((int)size);
+ lob.setBlob(null);
+ getHibernateSession().saveOrUpdate(lob);
+ }
+ }
+
+ private HibernateStoreLob getCreateHibernateStoreLob(byte[] idBytes)
+ {
+ final String id = HexUtil.bytesToHex(idBytes);
+ final Session session = getHibernateSession();
+ HibernateStoreLob lob = (HibernateStoreLob)session.get(HibernateStoreLob.class, id);
+ if (lob == null)
+ {
+ lob = new HibernateStoreLob();
+ lob.setId(id);
+ }
+
+ return lob;
}
@Override
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreLob.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreLob.java
new file mode 100644
index 0000000000..038abd56bd
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreLob.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2004 - 2010 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 and implementation
+ * Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.server.internal.hibernate;
+
+import java.sql.Blob;
+import java.sql.Clob;
+
+/**
+ * Object used to store clob and lob.
+ *
+ * @author Martin Taal
+ */
+public class HibernateStoreLob
+{
+ // note size -1 is used to flag a new state
+ private static int NEW_FLAG_SIZE = -1;
+
+ private String id;
+
+ private Clob clob;
+
+ private Blob blob;
+
+ private int size = NEW_FLAG_SIZE;
+
+ public boolean isNew()
+ {
+ return size == NEW_FLAG_SIZE;
+ }
+
+ public int getSize()
+ {
+ return size;
+ }
+
+ public void setSize(int size)
+ {
+ this.size = size;
+ }
+
+ public String getId()
+ {
+ return id;
+ }
+
+ public void setId(String id)
+ {
+ this.id = id;
+ }
+
+ public Clob getClob()
+ {
+ return clob;
+ }
+
+ public void setClob(Clob clob)
+ {
+ this.clob = clob;
+ }
+
+ public Blob getBlob()
+ {
+ return blob;
+ }
+
+ public void setBlob(Blob blob)
+ {
+ this.blob = blob;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/SystemProperty.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/SystemProperty.java
new file mode 100644
index 0000000000..df12165334
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/SystemProperty.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2004 - 2010 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 and implementation
+ * Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.server.internal.hibernate;
+
+/**
+ * Is used to store and retrieve properties in the database.
+ *
+ * @author Martin Taal
+ */
+public class SystemProperty
+{
+ private String name;
+
+ private String value;
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ public void setValue(String value)
+ {
+ this.value = value;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOBlobUserType.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOBlobUserType.java
new file mode 100644
index 0000000000..e021e3527e
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOBlobUserType.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2004 - 2010 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
+ * Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.server.internal.hibernate.tuplizer;
+
+import org.eclipse.emf.cdo.common.model.lob.CDOBlob;
+import org.eclipse.emf.cdo.common.model.lob.CDOLobUtil;
+
+/**
+ * Persists a {@link CDOBlob} in the DB.
+ */
+public class CDOBlobUserType extends CDOLobUserType
+{
+ public Class<?> returnedClass()
+ {
+ return CDOBlob.class;
+ }
+
+ @Override
+ protected Object createLob(byte[] id, long size)
+ {
+ return CDOLobUtil.createBlob(id, size);
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOClobUserType.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOClobUserType.java
new file mode 100644
index 0000000000..3370160123
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOClobUserType.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2004 - 2010 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
+ * Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.server.internal.hibernate.tuplizer;
+
+import org.eclipse.emf.cdo.common.model.lob.CDOClob;
+import org.eclipse.emf.cdo.common.model.lob.CDOLobUtil;
+
+/**
+ * Persists a {@link CDOClob} in the DB.
+ */
+public class CDOClobUserType extends CDOLobUserType
+{
+ public Class<?> returnedClass()
+ {
+ return CDOClob.class;
+ }
+
+ @Override
+ protected Object createLob(byte[] id, long size)
+ {
+ return CDOLobUtil.createClob(id, size);
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOCustomTypeUserType.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOCustomTypeUserType.java
new file mode 100644
index 0000000000..36f99606f6
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOCustomTypeUserType.java
@@ -0,0 +1,125 @@
+/**
+ * Copyright (c) 2004 - 2010 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
+ * Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.server.internal.hibernate.tuplizer;
+
+import org.hibernate.Hibernate;
+import org.hibernate.usertype.ParameterizedType;
+import org.hibernate.usertype.UserType;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Properties;
+
+/**
+ * Standard user type used for all custom types.
+ */
+public class CDOCustomTypeUserType implements UserType, ParameterizedType
+{
+ private static final int[] SQL_TYPES = { Types.VARCHAR };
+
+ public void setParameterValues(Properties arg0)
+ {
+ }
+
+ public Class<?> returnedClass()
+ {
+ return Object.class;
+ }
+
+ public int[] sqlTypes()
+ {
+ return SQL_TYPES;
+ }
+
+ public boolean isMutable()
+ {
+ return false;
+ }
+
+ public Object deepCopy(Object value)
+ {
+ return value;
+ }
+
+ public boolean equals(Object x, Object y)
+ {
+ if (x == y)
+ {
+ return true;
+ }
+
+ if (x == null || y == null)
+ {
+ return false;
+ }
+
+ return x.equals(y);
+ }
+
+ public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException
+ {
+ try
+ {
+ final String value = (String)Hibernate.STRING.nullSafeGet(rs, names[0]);
+ if (rs.wasNull())
+ {
+ return null;
+ }
+
+ return value;
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void nullSafeSet(PreparedStatement statement, Object value, int index) throws SQLException
+ {
+ try
+ {
+ if (value == null)
+ {
+ statement.setNull(index, Types.VARCHAR);
+ return;
+ }
+ statement.setString(index, value.toString());
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public Serializable disassemble(Object value)
+ {
+ return (Serializable)value;
+ }
+
+ public Object assemble(Serializable cachedValue, Object owner)
+ {
+ return cachedValue;
+ }
+
+ public Object replace(Object original, Object target, Object owner)
+ {
+ return original;
+ }
+
+ public int hashCode(Object x)
+ {
+ return x.hashCode();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOLobUserType.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOLobUserType.java
new file mode 100644
index 0000000000..c9e287db47
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDOLobUserType.java
@@ -0,0 +1,150 @@
+/**
+ * Copyright (c) 2004 - 2010 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
+ * Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.server.internal.hibernate.tuplizer;
+
+import org.eclipse.emf.cdo.common.model.lob.CDOBlob;
+import org.eclipse.emf.cdo.common.model.lob.CDOClob;
+import org.eclipse.emf.cdo.common.model.lob.CDOLob;
+
+import org.eclipse.net4j.util.HexUtil;
+
+import org.hibernate.Hibernate;
+import org.hibernate.usertype.ParameterizedType;
+import org.hibernate.usertype.UserType;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Properties;
+
+/**
+ * Base class for persisting {@link CDOBlob} and {@link CDOClob}.
+ */
+public abstract class CDOLobUserType implements UserType, ParameterizedType
+{
+ private static final String SEPARATOR = " - ";
+
+ private static final int[] SQL_TYPES = { Types.CLOB };
+
+ public CDOLobUserType()
+ {
+ }
+
+ public void setParameterValues(Properties arg0)
+ {
+ }
+
+ public int[] sqlTypes()
+ {
+ return SQL_TYPES;
+ }
+
+ public boolean isMutable()
+ {
+ return false;
+ }
+
+ public Object deepCopy(Object value)
+ {
+ return value;
+ }
+
+ public boolean equals(Object x, Object y)
+ {
+ if (x == y)
+ {
+ return true;
+ }
+
+ if (x == null || y == null)
+ {
+ return false;
+ }
+
+ return x.equals(y);
+ }
+
+ public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException
+ {
+ try
+ {
+ final String value = (String)Hibernate.STRING.nullSafeGet(rs, names[0]);
+ if (rs.wasNull())
+ {
+ return null;
+ }
+
+ return convertStringToLob(value);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void nullSafeSet(PreparedStatement statement, Object value, int index) throws SQLException
+ {
+ try
+ {
+ final CDOLob<?> cdoLob = (CDOLob<?>)value;
+
+ if (value == null || cdoLob.getSize() == 0)
+ {
+ statement.setNull(index, Types.VARCHAR);
+ return;
+ }
+ statement.setString(index, convertLobToString(cdoLob));
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public Serializable disassemble(Object value)
+ {
+ return (Serializable)value;
+ }
+
+ public Object assemble(Serializable cachedValue, Object owner)
+ {
+ return cachedValue;
+ }
+
+ private String convertLobToString(CDOLob<?> lob)
+ {
+ return HexUtil.bytesToHex(lob.getID()) + SEPARATOR + lob.getSize();
+ }
+
+ private Object convertStringToLob(String lobId)
+ {
+ int pos = lobId.indexOf(SEPARATOR);
+
+ byte[] id = HexUtil.hexToBytes(lobId.substring(0, pos));
+ long size = Long.parseLong(lobId.substring(pos + 1));
+ return createLob(id, size);
+ }
+
+ protected abstract Object createLob(byte[] id, long size);
+
+ public Object replace(Object original, Object target, Object owner)
+ {
+ return original;
+ }
+
+ public int hashCode(Object x)
+ {
+ return x.hashCode();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDORevisionTuplizer.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDORevisionTuplizer.java
index 1764d53096..eb4913e7c5 100644
--- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDORevisionTuplizer.java
+++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDORevisionTuplizer.java
@@ -20,11 +20,13 @@ import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.net4j.util.om.trace.ContextTracer;
+import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcoreFactory;
import org.hibernate.EntityMode;
import org.hibernate.EntityNameResolver;
@@ -242,6 +244,7 @@ public class CDORevisionTuplizer extends AbstractEntityTuplizer
if (mappedProperty == mappedEntity.getIdentifierProperty())
{
+ setIdentifierTypeAsAnnotation(mappedProperty);
return new CDOIDPropertySetter(this, mappedProperty.getName());
}
@@ -322,4 +325,20 @@ public class CDORevisionTuplizer extends AbstractEntityTuplizer
{
return false;
}
+
+ private void setIdentifierTypeAsAnnotation(Property prop)
+ {
+ EAnnotation eAnnotation = getEClass().getEAnnotation(HibernateStore.ID_TYPE_EANNOTATION_SOURCE);
+ if (eAnnotation == null)
+ {
+ eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
+ eAnnotation.setSource(HibernateStore.ID_TYPE_EANNOTATION_SOURCE);
+ eAnnotation.getDetails().put(HibernateStore.ID_TYPE_EANNOTATION_KEY, prop.getType().getName());
+ getEClass().getEAnnotations().add(eAnnotation);
+ }
+ else if (!eAnnotation.getDetails().containsKey(HibernateStore.ID_TYPE_EANNOTATION_KEY))
+ {
+ eAnnotation.getDetails().put(HibernateStore.ID_TYPE_EANNOTATION_KEY, prop.getType().getName());
+ }
+ }
}
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 0d80e10c1c..0dff31d7e5 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
@@ -177,6 +177,11 @@ public class WrappedHibernateList implements InternalCDOList
protected CDOID getCDOID(Object o)
{
+ if (o instanceof CDOID)
+ {
+ return (CDOID)o;
+ }
+
return HibernateUtil.getInstance().getCDOID(o);
}
@@ -228,7 +233,13 @@ public class WrappedHibernateList implements InternalCDOList
public Object get(int index)
{
- final Object value = getObject(getDelegate().get(index));
+ final Object delegateValue = getDelegate().get(index);
+ if (delegateValue instanceof CDOID)
+ {
+ return delegateValue;
+ }
+
+ final Object value = getObject(delegateValue);
if (value instanceof CDORevision || value instanceof HibernateProxy)
{
return HibernateUtil.getInstance().getCDOID(value);

Back to the top