org.bonitasoft.engine.persistence.TenantHibernatePersistenceService.java Source code

Java tutorial

Introduction

Here is the source code for org.bonitasoft.engine.persistence.TenantHibernatePersistenceService.java

Source

/**
 * Copyright (C) 2015 BonitaSoft S.A.
 * BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation
 * version 2.1 of the License.
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301, USA.
 **/
package org.bonitasoft.engine.persistence;

import java.util.List;
import java.util.Properties;
import java.util.Set;

import javax.sql.DataSource;

import org.bonitasoft.engine.commons.ClassReflector;
import org.bonitasoft.engine.commons.exceptions.SReflectException;
import org.bonitasoft.engine.log.technical.TechnicalLogSeverity;
import org.bonitasoft.engine.log.technical.TechnicalLoggerService;
import org.bonitasoft.engine.sequence.SequenceManager;
import org.bonitasoft.engine.services.SPersistenceException;
import org.bonitasoft.engine.sessionaccessor.ReadSessionAccessor;
import org.bonitasoft.engine.sessionaccessor.STenantIdNotSetException;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.StaleStateException;
import org.hibernate.exception.LockAcquisitionException;

/**
 * @author Baptiste Mesta
 * @author Nicolas Chabanoles
 * @author Yanyan Liu
 * @author Matthieu Chaffotte
 * @author Celine Souchet
 */
public class TenantHibernatePersistenceService extends AbstractHibernatePersistenceService {

    private static final String TENANT_ID = "tenantId";

    private static final String TENANT_FILTER = "tenantFilter";

    private final ReadSessionAccessor sessionAccessor;

    public TenantHibernatePersistenceService(final String name, final ReadSessionAccessor sessionAccessor,
            final HibernateConfigurationProvider hbmConfigurationProvider,
            final Properties extraHibernateProperties, final String likeEscapeCharacter,
            final TechnicalLoggerService logger, final SequenceManager sequenceManager, final DataSource datasource,
            final boolean enableWordSearch, final Set<String> wordSearchExclusionMappings)
            throws SPersistenceException, ClassNotFoundException {
        super(name, hbmConfigurationProvider, extraHibernateProperties, likeEscapeCharacter, logger,
                sequenceManager, datasource, enableWordSearch, wordSearchExclusionMappings);
        this.sessionAccessor = sessionAccessor;
    }

    protected void updateTenantFilter(final Session session, final boolean useTenant) throws SPersistenceException {
        if (useTenant) {
            try {
                session.enableFilter(TENANT_FILTER).setParameter(TENANT_ID, getTenantId());
            } catch (final STenantIdNotSetException e) {
                throw new SPersistenceException(e);
            }
        } else {
            session.disableFilter(TENANT_FILTER);
        }
    }

    protected void setTenant(final PersistentObject entity) throws SPersistenceException {
        if (entity == null) {
            return;
        }
        // if this entity has no id, set it
        Long tenantId = null;
        try {
            tenantId = ClassReflector.invokeGetter(entity, "getTenantId");
        } catch (final Exception e) {
            // this is a new object to save
        }
        if (tenantId == null || tenantId == -1 || tenantId == 0) {
            setTenantByClassReflector(entity, tenantId);
        }
    }

    private void setTenantByClassReflector(final PersistentObject entity, Long tenantId)
            throws SPersistenceException {
        try {
            tenantId = getTenantId();
            ClassReflector.invokeSetter(entity, "setTenantId", long.class, tenantId);
        } catch (final SReflectException e) {
            throw new SPersistenceException("Can't set tenantId = <" + tenantId + "> on entity." + entity, e);
        } catch (final STenantIdNotSetException e) {
            throw new SPersistenceException("Can't set tenantId = <" + tenantId + "> on entity." + entity, e);
        }
    }

    @Override
    protected Session getSession(final boolean useTenant) throws SPersistenceException {
        final Session session = super.getSession(useTenant);
        updateTenantFilter(session, useTenant);
        return session;
    }

    @Override
    public void flushStatements() throws SPersistenceException {
        super.flushStatements(true);
    }

    @Override
    public void delete(final PersistentObject entity) throws SPersistenceException {
        try {
            if (logger.isLoggable(getClass(), TechnicalLogSeverity.DEBUG)) {
                logger.log(this.getClass(), TechnicalLogSeverity.DEBUG, "[Tenant] Deleting instance of class "
                        + entity.getClass().getSimpleName() + " with id=" + entity.getId());
            }
            final Class<? extends PersistentObject> mappedClass = getMappedClass(entity.getClass());
            final Session session = getSession(true);
            final Object pe = session.get(mappedClass, new PersistentObjectId(entity.getId(), getTenantId()));
            session.delete(pe);
        } catch (final AssertionFailure | LockAcquisitionException | StaleStateException e) {
            throw new SRetryableException(e);
        } catch (final STenantIdNotSetException | HibernateException e) {
            throw new SPersistenceException(e);
        }
    }

    @Override
    public void insert(final PersistentObject entity) throws SPersistenceException {
        setTenant(entity);
        super.insert(entity);
    }

    @Override
    public void insertInBatch(final List<PersistentObject> entities) throws SPersistenceException {
        for (final PersistentObject entity : entities) {
            setTenant(entity);
        }
        super.insertInBatch(entities);
    }

    @Override
    protected long getTenantId() throws STenantIdNotSetException {
        return sessionAccessor.getTenantId();
    }

    @SuppressWarnings("unchecked")
    @Override
    <T extends PersistentObject> T selectById(final Session session, final SelectByIdDescriptor<T> selectDescriptor)
            throws SBonitaReadException {
        try {
            final PersistentObjectId id = new PersistentObjectId(selectDescriptor.getId(), getTenantId());
            Class<? extends PersistentObject> mappedClass = null;
            mappedClass = getMappedClass(selectDescriptor.getEntityType());
            return (T) session.get(mappedClass, id);
        } catch (final STenantIdNotSetException e) {
            return super.selectById(session, selectDescriptor);
        } catch (final AssertionFailure | LockAcquisitionException | StaleStateException e) {
            throw new SRetryableException(e);
        } catch (final SPersistenceException | HibernateException e) {
            throw new SBonitaReadException(e);
        }
    }

    @Override
    public void deleteByTenant(final Class<? extends PersistentObject> entityClass,
            final List<FilterOption> filters) throws SPersistenceException {
        try {
            final Session session = getSession(true);
            final String entityClassName = entityClass.getCanonicalName();
            final boolean enableWordSearch = isWordSearchEnabled(entityClass);

            final Query query = session.createQuery(getQueryString(entityClassName, filters, enableWordSearch));
            query.setLong(TENANT_ID, getTenantId());
            query.executeUpdate();
            if (logger.isLoggable(getClass(), TechnicalLogSeverity.DEBUG)) {
                logger.log(this.getClass(), TechnicalLogSeverity.DEBUG,
                        "[Tenant] Deleting all instance of class " + entityClass.getClass().getSimpleName());
            }
        } catch (final STenantIdNotSetException e) {
            throw new SPersistenceException(e);
        }
    }

    private String getQueryString(final String entityClassName, final List<FilterOption> filters,
            final boolean enableWordSearch) {
        if (filters == null || filters.isEmpty()) {
            return "DELETE FROM " + entityClassName + " WHERE tenantId= :tenantId";
        }
        return getQueryWithFilters("DELETE FROM " + entityClassName + " "
                + getClassAliasMappings().get(entityClassName) + " WHERE tenantId= :tenantId", filters, null,
                enableWordSearch);
    }

}