Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.engine.impl.db;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiOptimisticLockingException;
import org.activiti.engine.ActivitiWrongDbException;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.ActivitiVariableEvent;
import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti.engine.impl.DeploymentQueryImpl;
import org.activiti.engine.impl.ExecutionQueryImpl;
import org.activiti.engine.impl.GroupQueryImpl;
import org.activiti.engine.impl.HistoricActivityInstanceQueryImpl;
import org.activiti.engine.impl.HistoricDetailQueryImpl;
import org.activiti.engine.impl.HistoricProcessInstanceQueryImpl;
import org.activiti.engine.impl.HistoricTaskInstanceQueryImpl;
import org.activiti.engine.impl.HistoricVariableInstanceQueryImpl;
import org.activiti.engine.impl.JobQueryImpl;
import org.activiti.engine.impl.ModelQueryImpl;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.ProcessDefinitionQueryImpl;
import org.activiti.engine.impl.ProcessInstanceQueryImpl;
import org.activiti.engine.impl.TaskQueryImpl;
import org.activiti.engine.impl.UserQueryImpl;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.db.upgrade.DbUpgradeStep;
import org.activiti.engine.impl.history.HistoryLevel;
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.persistence.entity.PropertyEntity;
import org.activiti.engine.impl.persistence.entity.VariableInstanceEntity;
import org.activiti.engine.impl.util.IoUtil;
import org.activiti.engine.impl.util.ReflectUtil;
import org.activiti.engine.impl.variable.DeserializedObject;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** responsibilities:
* - delayed flushing of inserts updates and deletes
* - optional dirty checking
* - db specific statement name mapping
*
* @author Tom Baeyens
* @author Joram Barrez
*/
public class DbSqlSession implements Session {
private static final Logger log = LoggerFactory.getLogger(DbSqlSession.class);
private static final Pattern CLEAN_VERSION_REGEX = Pattern.compile("\\d\\.\\d*");
private static final List ACTIVITI_VERSIONS = new ArrayList();
static {
/* Previous */
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.7"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.8"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.9"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.10"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.11"));
// 5.12.1 was a bugfix release on 5.12 and did NOT change the version in ACT_GE_PROPERTY
// On top of that, DB2 create script for 5.12.1 was shipped with a 'T' suffix ...
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.12", Arrays.asList("5.12.1", "5.12T")));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.13"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.14"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.15"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.15.1"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.16"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.16.1"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.16.2-SNAPSHOT"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.16.2"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.16.3.0"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.16.4.0"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.17.0.0"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.17.0.1"));
ACTIVITI_VERSIONS.add(new ActivitiVersion("5.17.0.2"));
/* Current */
ACTIVITI_VERSIONS.add(new ActivitiVersion(ProcessEngine.VERSION));
}
protected SqlSession sqlSession;
protected DbSqlSessionFactory dbSqlSessionFactory;
protected List insertedObjects = new ArrayList();
protected Map, Map> cachedObjects = new HashMap, Map>();
protected List deleteOperations = new ArrayList();
protected List deserializedObjects = new ArrayList();
protected String connectionMetadataDefaultCatalog;
protected String connectionMetadataDefaultSchema;
protected boolean isOptimizeDeleteOperationsEnabled;
public DbSqlSession(DbSqlSessionFactory dbSqlSessionFactory) {
this.dbSqlSessionFactory = dbSqlSessionFactory;
this.isOptimizeDeleteOperationsEnabled = dbSqlSessionFactory.isOptimizeDeleteOperationsEnabled();
this.sqlSession = dbSqlSessionFactory
.getSqlSessionFactory()
.openSession();
}
public DbSqlSession(DbSqlSessionFactory dbSqlSessionFactory, Connection connection, String catalog, String schema) {
this.dbSqlSessionFactory = dbSqlSessionFactory;
this.sqlSession = dbSqlSessionFactory
.getSqlSessionFactory()
.openSession(connection);
this.connectionMetadataDefaultCatalog = catalog;
this.connectionMetadataDefaultSchema = schema;
}
// Touch ///////////////////////////////////////////////////////////////////
// brings the given persistenObject to the top if it already exists
public void touch(PersistentObject persistentObject) {
if (persistentObject.getId()==null) {
throw new ActivitiException("Cannot touch " + persistentObject.getClass() + " with no id");
}
if (insertedObjects.contains(persistentObject)) {
insertedObjects.remove(persistentObject);
insertedObjects.add(persistentObject);
cachePut(persistentObject, false);
}
}
// insert ///////////////////////////////////////////////////////////////////
public void insert(PersistentObject persistentObject) {
if (persistentObject.getId()==null) {
String id = dbSqlSessionFactory.getIdGenerator().getNextId();
persistentObject.setId(id);
}
insertedObjects.add(persistentObject);
cachePut(persistentObject, false);
}
// update ///////////////////////////////////////////////////////////////////
public void update(PersistentObject persistentObject) {
cachePut(persistentObject, false);
}
public int update(String statement, Object parameters) {
String updateStatement = dbSqlSessionFactory.mapStatement(statement);
return getSqlSession().update(updateStatement, parameters);
}
// delete ///////////////////////////////////////////////////////////////////
public void delete(String statement, Object parameter) {
deleteOperations.add(new BulkDeleteOperation(statement, parameter));
}
public void delete(PersistentObject persistentObject) {
for (DeleteOperation deleteOperation: deleteOperations) {
if (deleteOperation.sameIdentity(persistentObject)) {
log.debug("skipping redundant delete: {}", persistentObject);
return; // Skip this delete. It was already added.
}
}
deleteOperations.add(new CheckedDeleteOperation(persistentObject));
}
public interface DeleteOperation {
boolean sameIdentity(PersistentObject other);
void clearCache();
void execute();
}
/**
* Use this {@link DeleteOperation} to execute a dedicated delete statement.
* It is important to note there won't be any optimistic locking checks done
* for these kind of delete operations!
*
* For example, a usage of this operation would be to delete all variables for
* a certain execution, when that certain execution is removed. The optimistic locking
* happens on the execution, but the variables can be removed by a simple
* 'delete from var_table where execution_id is xxx'. It could very well be there
* are no variables, which would also work with this query, but not with the
* regular {@link CheckedDeleteOperation}.
*/
public class BulkDeleteOperation implements DeleteOperation {
private String statement;
private Object parameter;
public BulkDeleteOperation(String statement, Object parameter) {
this.statement = dbSqlSessionFactory.mapStatement(statement);
this.parameter = parameter;
}
@Override
public boolean sameIdentity(PersistentObject other) {
// this implementation is unable to determine what the identity of the removed object(s) will be.
return false;
}
@Override
public void clearCache() {
// this implementation cannot clear the object(s) to be removed from the cache.
}
@Override
public void execute() {
sqlSession.delete(statement, parameter);
}
@Override
public String toString() {
return "bulk delete: " + statement + "(" + parameter + ")";
}
}
/**
* A {@link DeleteOperation} that checks for concurrent modifications if the persistent object implements {@link HasRevision}.
* That is, it employs optimisting concurrency control. Used when the persistent object has been fetched already.
*/
public class CheckedDeleteOperation implements DeleteOperation {
protected final PersistentObject persistentObject;
public CheckedDeleteOperation(PersistentObject persistentObject) {
this.persistentObject = persistentObject;
}
@Override
public boolean sameIdentity(PersistentObject other) {
return persistentObject.getClass().equals(other.getClass())
&& persistentObject.getId().equals(other.getId());
}
@Override
public void clearCache() {
cacheRemove(persistentObject.getClass(), persistentObject.getId());
}
public void execute() {
String deleteStatement = dbSqlSessionFactory.getDeleteStatement(persistentObject.getClass());
deleteStatement = dbSqlSessionFactory.mapStatement(deleteStatement);
if (deleteStatement == null) {
throw new ActivitiException("no delete statement for " + persistentObject.getClass() + " in the ibatis mapping files");
}
// It only makes sense to check for optimistic locking exceptions for objects that actually have a revision
if (persistentObject instanceof HasRevision) {
int nrOfRowsDeleted = sqlSession.delete(deleteStatement, persistentObject);
if (nrOfRowsDeleted == 0) {
throw new ActivitiOptimisticLockingException(persistentObject + " was updated by another transaction concurrently");
}
} else {
sqlSession.delete(deleteStatement, persistentObject);
}
}
public PersistentObject getPersistentObject() {
return persistentObject;
}
@Override
public String toString() {
return "delete " + persistentObject;
}
}
/**
* A bulk version of the {@link CheckedDeleteOperation}.
*/
public class BulkCheckedDeleteOperation implements DeleteOperation {
protected Class extends PersistentObject> persistentObjectClass;
protected List persistentObjects = new ArrayList();
public BulkCheckedDeleteOperation(Class extends PersistentObject> persistentObjectClass) {
this.persistentObjectClass = persistentObjectClass;
}
public void addPersistentObject(PersistentObject persistentObject) {
persistentObjects.add(persistentObject);
}
@Override
public boolean sameIdentity(PersistentObject other) {
for (PersistentObject persistentObject : persistentObjects) {
if (persistentObject.getClass().equals(other.getClass()) && persistentObject.getId().equals(other.getId())) {
return true;
}
}
return false;
}
@Override
public void clearCache() {
for (PersistentObject persistentObject : persistentObjects) {
cacheRemove(persistentObject.getClass(), persistentObject.getId());
}
}
public void execute() {
if (persistentObjects.isEmpty()) {
return;
}
String bulkDeleteStatement = dbSqlSessionFactory.getBulkDeleteStatement(persistentObjectClass);
bulkDeleteStatement = dbSqlSessionFactory.mapStatement(bulkDeleteStatement);
if (bulkDeleteStatement == null) {
throw new ActivitiException("no bulk delete statement for " + persistentObjectClass + " in the mapping files");
}
// It only makes sense to check for optimistic locking exceptions for objects that actually have a revision
if (persistentObjects.get(0) instanceof HasRevision) {
int nrOfRowsDeleted = sqlSession.delete(bulkDeleteStatement, persistentObjects);
if (nrOfRowsDeleted < persistentObjects.size()) {
throw new ActivitiOptimisticLockingException("One of the entities " + persistentObjectClass
+ " was updated by another transaction concurrently while trying to do a bulk delete");
}
} else {
sqlSession.delete(bulkDeleteStatement, persistentObjects);
}
}
public Class extends PersistentObject> getPersistentObjectClass() {
return persistentObjectClass;
}
public void setPersistentObjectClass(
Class extends PersistentObject> persistentObjectClass) {
this.persistentObjectClass = persistentObjectClass;
}
public List getPersistentObjects() {
return persistentObjects;
}
public void setPersistentObjects(List persistentObjects) {
this.persistentObjects = persistentObjects;
}
@Override
public String toString() {
return "bulk delete of " + persistentObjects.size() + (!persistentObjects.isEmpty() ? " entities of " + persistentObjects.get(0).getClass() : 0 );
}
}
// select ///////////////////////////////////////////////////////////////////
@SuppressWarnings({ "rawtypes" })
public List selectList(String statement) {
return selectList(statement, null, 0, Integer.MAX_VALUE);
}
@SuppressWarnings("rawtypes")
public List selectList(String statement, Object parameter) {
return selectList(statement, parameter, 0, Integer.MAX_VALUE);
}
@SuppressWarnings("rawtypes")
public List selectList(String statement, Object parameter, Page page) {
if (page!=null) {
return selectList(statement, parameter, page.getFirstResult(), page.getMaxResults());
} else {
return selectList(statement, parameter, 0, Integer.MAX_VALUE);
}
}
@SuppressWarnings("rawtypes")
public List selectList(String statement, ListQueryParameterObject parameter, Page page) {
return selectList(statement, parameter);
}
@SuppressWarnings("rawtypes")
public List selectList(String statement, Object parameter, int firstResult, int maxResults) {
return selectList(statement, new ListQueryParameterObject(parameter, firstResult, maxResults));
}
@SuppressWarnings("rawtypes")
public List selectList(String statement, ListQueryParameterObject parameter) {
return selectListWithRawParameter(statement, parameter, parameter.getFirstResult(), parameter.getMaxResults());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public List selectListWithRawParameter(String statement, Object parameter, int firstResult, int maxResults) {
statement = dbSqlSessionFactory.mapStatement(statement);
if (firstResult == -1 || maxResults == -1) {
return Collections.EMPTY_LIST;
}
List loadedObjects = sqlSession.selectList(statement, parameter);
return filterLoadedObjects(loadedObjects);
}
@SuppressWarnings({ "rawtypes" })
public List selectListWithRawParameterWithoutFilter(String statement, Object parameter, int firstResult, int maxResults) {
statement = dbSqlSessionFactory.mapStatement(statement);
if (firstResult == -1 || maxResults == -1) {
return Collections.EMPTY_LIST;
}
return sqlSession.selectList(statement, parameter);
}
public Object selectOne(String statement, Object parameter) {
statement = dbSqlSessionFactory.mapStatement(statement);
Object result = sqlSession.selectOne(statement, parameter);
if (result instanceof PersistentObject) {
PersistentObject loadedObject = (PersistentObject) result;
result = cacheFilter(loadedObject);
}
return result;
}
@SuppressWarnings("unchecked")
public T selectById(Class entityClass, String id) {
T persistentObject = cacheGet(entityClass, id);
if (persistentObject!=null) {
return persistentObject;
}
String selectStatement = dbSqlSessionFactory.getSelectStatement(entityClass);
selectStatement = dbSqlSessionFactory.mapStatement(selectStatement);
persistentObject = (T) sqlSession.selectOne(selectStatement, id);
if (persistentObject==null) {
return null;
}
cachePut(persistentObject, true);
return persistentObject;
}
// internal session cache ///////////////////////////////////////////////////
@SuppressWarnings("rawtypes")
protected List filterLoadedObjects(List