org.eclipse.emf.cdo.server.internal.hibernate.HibernateStore.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.emf.cdo.server.internal.hibernate.HibernateStore.java

Source

/*
 * Copyright (c) 2008-2013, 2015 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
 *    Martin Taal - moved cdopackage handler to other class, changed configuration
 */
package org.eclipse.emf.cdo.server.internal.hibernate;

import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOID.ObjectType;
import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
import org.eclipse.emf.cdo.common.model.CDOModelUtil;
import org.eclipse.emf.cdo.eresource.EresourcePackage;
import org.eclipse.emf.cdo.etypes.EtypesPackage;
import org.eclipse.emf.cdo.internal.server.TransactionCommitContext.TransactionPackageRegistry;
import org.eclipse.emf.cdo.server.ISession;
import org.eclipse.emf.cdo.server.ITransaction;
import org.eclipse.emf.cdo.server.IView;
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.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.server.Store;
import org.eclipse.emf.cdo.spi.server.StoreAccessorPool;

import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.io.IOUtil;
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.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.teneo.Constants;
import org.eclipse.emf.teneo.PackageRegistryProvider;
import org.eclipse.emf.teneo.PersistenceOptions;
import org.eclipse.emf.teneo.annotations.mapper.PersistenceMappingBuilder;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedModel;
import org.eclipse.emf.teneo.hibernate.EMFInterceptor;
import org.eclipse.emf.teneo.hibernate.HbDataStore;
import org.eclipse.emf.teneo.hibernate.HbSessionDataStore;
import org.eclipse.emf.teneo.hibernate.auditing.AuditHandler;
import org.eclipse.emf.teneo.hibernate.auditing.AuditProcessHandler;
import org.eclipse.emf.teneo.hibernate.auditing.model.teneoauditing.TeneoAuditEntry;
import org.eclipse.emf.teneo.hibernate.auditing.model.teneoauditing.TeneoauditingPackage;
import org.eclipse.emf.teneo.hibernate.mapper.HibernateMappingGenerator;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.type.StandardBasicTypes;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * @author Eike Stepper
 * @author Martin Taal
 */
public class HibernateStore extends Store implements IHibernateStore {
    public static final String PERSISTENCE_XML = PersistenceOptions.PERSISTENCE_XML;

    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));

    private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, HibernateStore.class);

    private static final String RESOURCE_HBM_PATH = "mappings/resource.hbm.xml"; //$NON-NLS-1$

    private static final String HBM2DLL_UPDATE = "update"; //$NON-NLS-1$

    private static final String HBM2DLL_CREATE = "create"; //$NON-NLS-1$

    /**
     * Used to give different extensions of Hibernate a context when initializing
     */
    private static ThreadLocal<HibernateStore> currentHibernateStore = new ThreadLocal<HibernateStore>();

    private HbSessionDataStore cdoDataStore;

    private HibernateAuditHandler hibernateAuditHandler;

    private HibernatePackageHandler packageHandler;

    private IHibernateMappingProvider mappingProvider;

    private boolean doDropSchema;

    private SystemInformation systemInformation;

    private List<EPackage> auditEPackages;

    private Map<String, String> identifierPropertyNameByEntity;

    private Properties properties;

    // is initialized on get
    private CDOBranchPoint mainBranchHead;

    private String mappingXml = null;

    public HibernateStore(IHibernateMappingProvider mappingProvider) {
        this(mappingProvider, null);
    }

    public HibernateStore(IHibernateMappingProvider mappingProvider, Properties properties) {
        super(TYPE, OBJECT_ID_TYPES, set(ChangeFormat.REVISION),
                set(RevisionTemporality.NONE, RevisionTemporality.AUDITING), set(RevisionParallelism.NONE));
        this.mappingProvider = mappingProvider;
        packageHandler = new HibernatePackageHandler(this);
        this.properties = properties;

        if (TRACER.isEnabled() && mappingProvider != null) {
            TRACER.trace("HibernateStore with mappingProvider " + mappingProvider.getClass().getName()); //$NON-NLS-1$
        }
    }

    public boolean isAuditing() {
        return getRevisionTemporality() == RevisionTemporality.AUDITING;
    }

    public CDOBranchPoint getMainBranchHead() {
        if (mainBranchHead == null) {
            mainBranchHead = getRepository().getBranchManager().getMainBranch().getHead();
        }

        return mainBranchHead;
    }

    public String getIdentifierPropertyName(String entityName) {
        return identifierPropertyNameByEntity.get(entityName);
    }

    public boolean isMapped(EClass eClass) {
        return null != cdoDataStore.toEntityName(eClass);
    }

    public Properties getProperties() {
        if (properties == null || properties.isEmpty()) {
            properties = new Properties();

            final Map<String, String> storeProps = getRepository().getProperties();
            for (String key : storeProps.keySet()) {
                properties.setProperty(key, storeProps.get(key));
            }
        }

        return properties;
    }

    public void addEntityNameEClassMapping(String entityName, EClass eClass) {
        cdoDataStore.addEntityNameEClassMapping(entityName, eClass);
    }

    /**
     * Returns all model epackages, so no audit epackages or system
     * epackages.
     */
    public List<EPackage> getModelEPackages() {
        final List<EPackage> epacks = getPackageHandler().getEPackages();
        final ListIterator<EPackage> iterator = epacks.listIterator();
        while (iterator.hasNext()) {
            final EPackage epack = iterator.next();
            if (CDOModelUtil.isSystemPackage(epack) && epack != EtypesPackage.eINSTANCE) {
                iterator.remove();
            } else if (isAuditEPackage(epack)) {
                // an auditing package
                iterator.remove();
            }
        }
        return epacks;
    }

    private boolean isAuditEPackage(EPackage ePackage) {
        return TeneoauditingPackage.eNS_URI.equals(ePackage.getNsURI())
                || ePackage.getEAnnotation(Constants.ANNOTATION_SOURCE_AUDITING) != null;
    }

    public String getEntityName(EClass eClass) {
        if (eClass == null) {
            throw new IllegalArgumentException("EClass argument is null"); //$NON-NLS-1$
        }
        final String entityName = cdoDataStore.toEntityName(eClass);
        if (entityName == null) {
            throw new IllegalArgumentException("EClass " + eClass.getName() //$NON-NLS-1$
                    + " does not have an entity name, has it been mapped to Hibernate?"); //$NON-NLS-1$
        }

        return entityName;
    }

    public String getEntityName(CDOClassifierRef classifierRef) {
        if (classifierRef == null) {
            throw new IllegalArgumentException("classifierRef argument is null"); //$NON-NLS-1$
        }

        EClass eClass = (EClass) classifierRef.resolve(getRepository().getPackageRegistry());

        // initialize everything
        getHibernateSessionFactory();

        final String entityName = cdoDataStore.toEntityName(eClass);
        if (entityName == null) {
            throw new IllegalArgumentException("EClass " + classifierRef //$NON-NLS-1$
                    + " does not have an entity name, has it been mapped to Hibernate?"); //$NON-NLS-1$
        }

        return entityName;
    }

    public EClass getEClass(String entityName) {
        if (entityName == null) {
            throw new IllegalArgumentException("entityname argument is null"); //$NON-NLS-1$
        }

        final EClass eClass = cdoDataStore.toEClass(entityName);
        if (eClass == null) {
            throw new IllegalArgumentException("entityname " + entityName //$NON-NLS-1$
                    + " does not map to an EClass, has it been mapped to Hibernate?"); //$NON-NLS-1$
        }

        return eClass;
    }

    public Configuration getHibernateConfiguration() {
        return cdoDataStore.getConfiguration();
    }

    public synchronized SessionFactory getHibernateSessionFactory() {
        if (cdoDataStore == null) {
            if (TRACER.isEnabled()) {
                TRACER.trace("Initializing SessionFactory for HibernateStore"); //$NON-NLS-1$
            }

            currentHibernateStore.set(this);

            identifierPropertyNameByEntity = new HashMap<String, String>();

            try {
                initDataStore();

                // this has to be done before the classmapping is iterated
                // otherwise it is not initialized
                SessionFactory hibernateSessionFactory = cdoDataStore.getSessionFactory();
                ServiceRegistry serviceRegistry = ((SessionFactoryImpl) hibernateSessionFactory)
                        .getServiceRegistry();
                final EventListenerRegistry eventListenerRegistry = serviceRegistry
                        .getService(EventListenerRegistry.class);
                eventListenerRegistry.setListeners(EventType.MERGE, new CDOMergeEventListener());

                final Iterator<?> iterator = cdoDataStore.getConfiguration().getClassMappings();
                while (iterator.hasNext()) {
                    final PersistentClass pc = (PersistentClass) iterator.next();
                    if (pc.getIdentifierProperty() == null) {
                        // happens for featuremaps for now...
                        continue;
                    }

                    identifierPropertyNameByEntity.put(pc.getEntityName(), pc.getIdentifierProperty().getName());
                }
            } catch (Throwable t) {
                t.printStackTrace(System.err);
                if (TRACER.isEnabled()) {
                    TRACER.trace(t);
                }
                throw new RuntimeException(t);
            } finally {
                currentHibernateStore.set(null);
            }
        }

        return cdoDataStore.getSessionFactory();
    }

    public void ensureCorrectPackageRegistry() {
        if (cdoDataStore == null) {
            return;
        }
        if (cdoDataStore.getPackageRegistry() instanceof TransactionPackageRegistry) {
            setInternalPackageRegistry();
        }
    }

    private synchronized void setInternalPackageRegistry() {
        cdoDataStore.setPackageRegistry(getRepository().getPackageRegistry(false));
    }

    public Connection getConnection() {
        String connectionURL = getProperties().getProperty("hibernate.connection.url");
        String userName = getProperties().getProperty("hibernate.connection.username");
        String passWord = getProperties().getProperty("hibernate.connection.password");

        try {
            Connection connection = DriverManager.getConnection(connectionURL, userName, passWord);
            if (connection == null) {
                throw new DBException("No connection from driver manager: " + connectionURL); //$NON-NLS-1$
            }

            String autoCommit = getProperties().getProperty("hibernate.connection.autocommit");
            if (autoCommit != null) {
                connection.setAutoCommit(Boolean.valueOf(autoCommit));
            }

            return connection;
        } catch (SQLException ex) {
            throw new DBException(ex);
        }
    }

    @Deprecated
    public boolean isLocal(CDOID id) {
        throw new UnsupportedOperationException();
    }

    public CDOID createObjectID(String val) {
        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");
        }

        final String idTypeStr = typeEAnnotation.getDetails().get(ID_TYPE_EANNOTATION_KEY);
        if (StandardBasicTypes.STRING.getName().equals(idTypeStr)) {
            return HibernateUtil.getInstance().createCDOID(classifierRef, idPart);
        } else if (StandardBasicTypes.LONG.getName().equals(idTypeStr)) {
            return HibernateUtil.getInstance().createCDOID(classifierRef, new Long(idPart));
        } else {
            throw new IllegalArgumentException("ID type " + idTypeStr + " not supported ");
        }
    }

    @Override
    public HibernateStoreAccessor createReader(ISession session) {
        return new HibernateStoreAccessor(this, session);
    }

    @Override
    public HibernateStoreAccessor createWriter(ITransaction transaction) {
        return new HibernateStoreAccessor(this, transaction);
    }

    public Map<String, String> getPersistentProperties(Set<String> names) {
        final Map<String, String> result = packageHandler.getSystemProperties();
        if (names == null || names.isEmpty()) {
            return result;
        }
        final Map<String, String> filteredResult = new HashMap<String, String>();
        for (String name : names) {
            if (result.containsKey(name)) {
                filteredResult.put(name, result.get(name));
            }
        }
        return filteredResult;
    }

    public void setPersistentProperties(Map<String, String> properties) {
        packageHandler.setSystemProperties(properties);
    }

    public void removePersistentProperties(Set<String> names) {
        final Map<String, String> props = getPersistentProperties(null);
        for (String name : names) {
            props.remove(name);
        }
        setPersistentProperties(props);
    }

    public synchronized int getNextPackageID() {
        return packageHandler.getNextPackageID();
    }

    public synchronized int getNextClassID() {
        return packageHandler.getNextClassID();
    }

    public synchronized int getNextFeatureID() {
        return packageHandler.getNextFeatureID();
    }

    public long getCreationTime() {
        return getSystemInformation().getCreationTime();
    }

    public void setCreationTime(long creationTime) {
        getSystemInformation().setCreationTime(creationTime);
    }

    public HibernatePackageHandler getPackageHandler() {
        return packageHandler;
    }

    // TODO: synchronize??
    @Override
    protected void doActivate() throws Exception {
        super.doActivate();
        packageHandler.activate();
    }

    @Override
    protected void doDeactivate() throws Exception {
        Configuration configuration = null;
        if (cdoDataStore != null) {
            configuration = cdoDataStore.getConfiguration();
            if (TRACER.isEnabled()) {
                TRACER.trace("Closing SessionFactory"); //$NON-NLS-1$
            }
            cdoDataStore.close();
        }

        // and now do the drop action
        if (configuration != null && doDropSchema) {
            final SchemaExport se = new SchemaExport(configuration);
            se.drop(false, true);
        }

        cdoDataStore = null;
        hibernateAuditHandler = null;
        // get rid of the audit epackages
        if (auditEPackages != null) {
            for (EPackage ePackage : auditEPackages) {
                getRepository().getPackageRegistry().remove(ePackage.getNsURI());
            }
            auditEPackages = null;
        }
        LifecycleUtil.deactivate(packageHandler, OMLogger.Level.WARN);
        super.doDeactivate();
    }

    @Override
    protected StoreAccessorPool getReaderPool(ISession session, boolean forReleasing) {
        // TODO Consider usings multiple pools for readers (e.g. bound to the session context)
        return null;
    }

    @Override
    protected StoreAccessorPool getWriterPool(IView view, boolean forReleasing) {
        // TODO Consider usings multiple pools for writers (e.g. bound to the session context)
        return null;
    }

    // is called after a new package has been added
    // TODO: synchronize??
    // TODO: combine with doActivate/doDeactivate??
    // TODO: assumes that packageHandler has been reset
    protected void reInitialize() {
        if (TRACER.isEnabled()) {
            TRACER.trace("Re-Initializing HibernateStore"); //$NON-NLS-1$
        }

        if (cdoDataStore != null) {
            if (!cdoDataStore.isClosed()) {
                if (TRACER.isEnabled()) {
                    TRACER.trace("Closing SessionFactory"); //$NON-NLS-1$
                }

                cdoDataStore.close();
            }

            cdoDataStore = null;
        }
    }

    protected void initDataStore() {
        if (TRACER.isEnabled()) {
            TRACER.trace("Initializing Configuration"); //$NON-NLS-1$
        }

        InputStream in = null;

        try {
            PackageRegistryProvider.getInstance().setThreadPackageRegistry(getRepository().getPackageRegistry());

            cdoDataStore = new CDODataStore();
            hibernateAuditHandler = new HibernateAuditHandler();
            hibernateAuditHandler.setCdoDataStore(cdoDataStore);
            hibernateAuditHandler.setHibernateStore(this);

            cdoDataStore.setResetConfigurationOnInitialization(false);
            cdoDataStore.setName("cdo");
            cdoDataStore.setPackageRegistry(getRepository().getPackageRegistry());
            cdoDataStore.getExtensionManager().registerExtension(EMFInterceptor.class.getName(),
                    CDOInterceptor.class.getName());
            cdoDataStore.getExtensionManager().registerExtension(AuditHandler.class.getName(),
                    CDOAuditHandler.class.getName());
            cdoDataStore.getExtensionManager().registerExtension(AuditProcessHandler.class.getName(),
                    CDOAuditProcessHandler.class.getName());

            // don't do any persistence xml mapping in this datastore
            // 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
            // properties object
            final Properties props = new Properties();
            props.putAll(getProperties());
            props.remove(PersistenceOptions.PERSISTENCE_XML);

            if (!props.containsKey(PersistenceOptions.HANDLE_UNSET_AS_NULL)) {
                props.setProperty(PersistenceOptions.HANDLE_UNSET_AS_NULL, "true");
            }

            cdoDataStore.setDataStoreProperties(props);
            Configuration hibernateConfiguration = cdoDataStore.getConfiguration();

            if (mappingProvider != null) {
                mappingProvider.setHibernateStore(this);
                mappingXml = mappingProvider.getMapping();
                hibernateConfiguration.addXML(mappingXml);
            }

            if (TRACER.isEnabled()) {
                TRACER.trace("Adding resource.hbm.xml to configuration"); //$NON-NLS-1$
            }

            in = OM.BUNDLE.getInputStream(RESOURCE_HBM_PATH);
            hibernateConfiguration.addInputStream(in);
            // hibernateConfiguration.setInterceptor(new CDOInterceptor());

            hibernateConfiguration.setProperties(props);

            // prevent the drop on close because the sessionfactory is also closed when
            // new packages are written to the db, so only do a real drop at deactivate
            if (hibernateConfiguration.getProperty(Environment.HBM2DDL_AUTO) != null
                    && hibernateConfiguration.getProperty(Environment.HBM2DDL_AUTO).startsWith(HBM2DLL_CREATE)) {
                doDropSchema = true;
                // note that the value create also re-creates the db and drops the old one
                hibernateConfiguration.setProperty(Environment.HBM2DDL_AUTO, HBM2DLL_UPDATE);
                cdoDataStore.getDataStoreProperties().setProperty(Environment.HBM2DDL_AUTO, HBM2DLL_UPDATE);
            } else {
                doDropSchema = false;
            }

            final List<EPackage> ePackages = new ArrayList<EPackage>(packageHandler.getEPackages());

            // get rid of the system packages
            for (EPackage ePackage : packageHandler.getEPackages()) {
                if (CDOModelUtil.isSystemPackage(ePackage) && ePackage != EtypesPackage.eINSTANCE) {
                    ePackages.remove(ePackage);
                }
            }
            // remove the persistence xml if no epackages as this won't work without
            // epackages
            if (ePackages.size() == 0 && props.getProperty(PersistenceOptions.PERSISTENCE_XML) != null) {
                cdoDataStore.getDataStoreProperties().remove(PersistenceOptions.PERSISTENCE_XML);
            }

            if (isAuditing()) {
                auditEPackages = createAuditEPackages(cdoDataStore);
                final String auditMapping = mapAuditingEPackages(cdoDataStore, auditEPackages);
                // System.err.println(auditMapping);
                hibernateConfiguration.addXML(auditMapping);
                cdoDataStore.setAuditing(true);
            }
            cdoDataStore.setEPackages(ePackages.toArray(new EPackage[0]));
        } catch (Exception ex) {
            throw WrappedException.wrap(ex);
        } finally {
            PackageRegistryProvider.getInstance().setThreadPackageRegistry(null);
            IOUtil.close(in);
        }
    }

    public static HibernateStore getCurrentHibernateStore() {
        return currentHibernateStore.get();
    }

    public boolean isFirstStart() {
        return getSystemInformation().isFirstTime();
    }

    private SystemInformation getSystemInformation() {
        if (systemInformation == null) {
            systemInformation = getPackageHandler().getSystemInformation();
        }

        return systemInformation;
    }

    public String getMappingXml() {
        return mappingXml;
    }

    private List<EPackage> createAuditEPackages(HbDataStore dataStore) {
        final PersistenceOptions po = dataStore.getPersistenceOptions();

        final List<EPackage> epacks = new ArrayList<EPackage>();
        for (EPackage ePackage : getModelEPackages()) {
            if (!CDOModelUtil.isSystemPackage(ePackage) && !isAuditEPackage(ePackage)) {
                epacks.add(dataStore.getAuditHandler().createAuditingEPackage(dataStore, ePackage,
                        getRepository().getPackageRegistry(), po));
            }
        }
        epacks.add(dataStore.getAuditHandler().createAuditingEPackage(dataStore,
                getRepository().getPackageRegistry().getEPackage(EresourcePackage.eNS_URI),
                getRepository().getPackageRegistry(), po));

        epacks.add(TeneoauditingPackage.eINSTANCE);

        getRepository().getPackageRegistry().put(TeneoauditingPackage.eNS_URI, TeneoauditingPackage.eINSTANCE);

        // also register them all in the non-transaction registry
        for (EPackage ePackage : epacks) {
            getRepository().getPackageRegistry(false).put(ePackage.getNsURI(), ePackage);
        }
        return epacks;
    }

    public String mapAuditingEPackages(HbDataStore dataStore, List<EPackage> auditEPackages) {
        // create a new persistence options to not change the original
        final Properties props = new Properties();
        props.putAll(dataStore.getPersistenceOptions().getProperties());
        props.remove(PersistenceOptions.PERSISTENCE_XML);
        if (props.containsKey(PersistenceOptions.AUDITING_PERSISTENCE_XML)) {
            props.setProperty(PersistenceOptions.PERSISTENCE_XML, PersistenceOptions.AUDITING_PERSISTENCE_XML);
        }
        final PersistenceOptions po = dataStore.getExtensionManager().getExtension(PersistenceOptions.class,
                new Object[] { props });
        PAnnotatedModel paModel = dataStore.getExtensionManager().getExtension(PersistenceMappingBuilder.class)
                .buildMapping(auditEPackages, po, dataStore.getExtensionManager(), dataStore.getPackageRegistry());
        final HibernateMappingGenerator hmg = dataStore.getExtensionManager()
                .getExtension(HibernateMappingGenerator.class);
        hmg.setPersistenceOptions(po);
        final String hbm = hmg.generateToString(paModel);

        return hbm;
    }

    private class CDODataStore extends HbSessionDataStore {

        private static final long serialVersionUID = 1L;

        @Override
        protected void addContainerMapping(PersistentClass pc) {
            // prevent container mapping for cdo objects
            if (pc.getTuplizerMap() != null) {
                for (Object tuplizerName : pc.getTuplizerMap().values()) {
                    if (((String) tuplizerName).contains("org.eclipse.emf.cdo")) {
                        return;
                    }
                }
            }
            super.addContainerMapping(pc);
        }

        @Override
        protected void mapModel() {
            if (getPersistenceOptions().getMappingFilePath() != null
                    || getPersistenceOptions().isUseMappingFile()) {
                super.mapModel();
            }
        }
    }

    public HibernateAuditHandler getHibernateAuditHandler() {
        ensureCorrectPackageRegistry();
        return hibernateAuditHandler;
    }

    public void setHibernateAuditHandler(HibernateAuditHandler hibernateAuditHandler) {
        this.hibernateAuditHandler = hibernateAuditHandler;
    }

    public static class CDOAuditProcessHandler extends AuditProcessHandler {

        private static final long serialVersionUID = 1L;

        @Override
        protected long getCommitTime() {
            if (HibernateThreadContext.isCommitContextSet()) {
                return HibernateThreadContext.getCommitContext().getCommitContext().getBranchPoint().getTimeStamp();
            }
            return super.getCommitTime();
        }

        @Override
        protected void doAuditWorkInSession(Session session, List<AuditWork> auditWorks) {
            try {
                PackageRegistryProvider.getInstance().setThreadPackageRegistry(getDataStore().getPackageRegistry());

                if (HibernateThreadContext.isCommitContextSet()) {
                    AuditProcessHandler.setCurrentUserName(
                            HibernateThreadContext.getCommitContext().getCommitContext().getUserID());
                    AuditProcessHandler.setCurrentComment(
                            HibernateThreadContext.getCommitContext().getCommitContext().getCommitComment());
                }
                super.doAuditWorkInSession(session, auditWorks);
            } finally {
                PackageRegistryProvider.getInstance().setThreadPackageRegistry(null);
                AuditProcessHandler.setCurrentUserName(null);
                AuditProcessHandler.setCurrentComment(null);
            }
        }

        @Override
        protected void setContainerInfo(Session session, TeneoAuditEntry auditEntry, Object entity) {
            if (!(entity instanceof InternalCDORevision)) {
                return;
            }
            final InternalCDORevision cdoRevision = (InternalCDORevision) entity;

            // set the resource id
            if (cdoRevision.getResourceID() != null) {
                auditEntry.setTeneo_resourceid(
                        getAuditHandler().entityToIdString(session, cdoRevision.getResourceID()));
            }

            if (cdoRevision.getContainerID() == null || cdoRevision.getContainerID() == CDOID.NULL) {
                return;
            }

            auditEntry.setTeneo_container_id(
                    getAuditHandler().entityToIdString(session, cdoRevision.getContainerID()));
            auditEntry.setTeneo_container_feature_id(cdoRevision.getContainingFeatureID());
        }

        @Override
        protected boolean performVersionCheck() {
            return true;
        }
    }

    public HbSessionDataStore getCDODataStore() {
        return cdoDataStore;
    }
}