package org.activiti.engine.impl.db; import org.activiti.engine.ActivitiException; import org.activiti.engine.ActivitiOptimisticLockingException; import org.activiti.engine.ActivitiWrongDbException; import org.activiti.engine.impl.*; 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.interceptor.Session; import org.activiti.engine.impl.persistence.cache.CachedEntity; import org.activiti.engine.impl.persistence.cache.EntityCache; import org.activiti.engine.impl.persistence.entity.Entity; import org.activiti.engine.impl.persistence.entity.ExecutionEntity; import org.activiti.engine.impl.persistence.entity.PropertyEntity; import org.activiti.engine.impl.util.IoUtil; import org.activiti.engine.impl.util.ReflectUtil; import org.apache.ibatis.session.SqlSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class DbSqlSession implements Session { private static final Logger log = LoggerFactory.getLogger(DbSqlSession.class); protected static final Pattern CLEAN_VERSION_REGEX = Pattern.compile("\\d\\.\\d*"); protected static final String LAST_V5_VERSION = "5.99.0.0"; protected static final List ACTIVITI_VERSIONS = new ArrayList(); protected SqlSession sqlSession; protected DbSqlSessionFactory dbSqlSessionFactory; protected EntityCache entityCache; protected Map, Map> insertedObjects = new HashMap(); protected Map, Map> deletedObjects = new HashMap(); protected Map, List> bulkDeleteOperations = new HashMap(); protected List updatedObjects = new ArrayList(); protected String connectionMetadataDefaultCatalog; protected String connectionMetadataDefaultSchema; public static String[] JDBC_METADATA_TABLE_TYPES; public DbSqlSession(DbSqlSessionFactory dbSqlSessionFactory, EntityCache entityCache) { this.dbSqlSessionFactory = dbSqlSessionFactory; this.sqlSession = dbSqlSessionFactory.getSqlSessionFactory().openSession(); this.entityCache = entityCache; this.connectionMetadataDefaultCatalog = dbSqlSessionFactory.getDatabaseCatalog(); this.connectionMetadataDefaultSchema = dbSqlSessionFactory.getDatabaseSchema(); } public DbSqlSession(DbSqlSessionFactory dbSqlSessionFactory, EntityCache entityCache, Connection connection, String catalog, String schema) { this.dbSqlSessionFactory = dbSqlSessionFactory; this.sqlSession = dbSqlSessionFactory.getSqlSessionFactory().openSession(connection); this.entityCache = entityCache; this.connectionMetadataDefaultCatalog = catalog; this.connectionMetadataDefaultSchema = schema; } public void insert(Entity entity) { if (entity.getId() == null) { String id = this.dbSqlSessionFactory.getIdGenerator().getNextId(); entity.setId(id); } Class clazz = entity.getClass(); if (!this.insertedObjects.containsKey(clazz)) { this.insertedObjects.put(clazz, new LinkedHashMap()); } ((Map)this.insertedObjects.get(clazz)).put(entity.getId(), entity); this.entityCache.put(entity, false); entity.setInserted(true); } public void update(Entity entity) { this.entityCache.put(entity, false); entity.setUpdated(true); } public int update(String statement, Object parameters) { String updateStatement = this.dbSqlSessionFactory.mapStatement(statement); return this.getSqlSession().update(updateStatement, parameters); } public void delete(String statement, Object parameter, Class entityClass) { if (!this.bulkDeleteOperations.containsKey(entityClass)) { this.bulkDeleteOperations.put(entityClass, new ArrayList(1)); } ((List)this.bulkDeleteOperations.get(entityClass)).add(new BulkDeleteOperation(this.dbSqlSessionFactory.mapStatement(statement), parameter)); } public void delete(Entity entity) { Class clazz = entity.getClass(); if (!this.deletedObjects.containsKey(clazz)) { this.deletedObjects.put(clazz, new LinkedHashMap()); } ((Map)this.deletedObjects.get(clazz)).put(entity.getId(), entity); entity.setDeleted(true); } public List selectList(String statement) { return this.selectList(statement, (Object)null, 0, Integer.MAX_VALUE); } public List selectList(String statement, Object parameter) { return this.selectList(statement, parameter, 0, Integer.MAX_VALUE); } public List selectList(String statement, Object parameter, boolean useCache) { return this.selectList(statement, parameter, 0, Integer.MAX_VALUE, useCache); } public List selectList(String statement, Object parameter, Page page) { return this.selectList(statement, parameter, page, true); } public List selectList(String statement, Object parameter, Page page, boolean useCache) { return page != null ? this.selectList(statement, parameter, page.getFirstResult(), page.getMaxResults(), useCache) : this.selectList(statement, parameter, 0, Integer.MAX_VALUE, useCache); } public List selectList(String statement, ListQueryParameterObject parameter, Page page) { return this.selectList(statement, parameter, page, true); } public List selectList(String statement, ListQueryParameterObject parameter, Page page, boolean useCache) { ListQueryParameterObject parameterToUse = parameter; if (parameterToUse == null) { parameterToUse = new ListQueryParameterObject(); } if (page != null) { parameterToUse.setFirstResult(page.getFirstResult()); parameterToUse.setMaxResults(page.getMaxResults()); } return this.selectList(statement, parameterToUse, useCache); } public List selectList(String statement, Object parameter, int firstResult, int maxResults) { return this.selectList(statement, parameter, firstResult, maxResults, true); } public List selectList(String statement, Object parameter, int firstResult, int maxResults, boolean useCache) { return this.selectList(statement, new ListQueryParameterObject(parameter, firstResult, maxResults), useCache); } public List selectList(String statement, ListQueryParameterObject parameter) { return this.selectList(statement, parameter, true); } public List selectList(String statement, ListQueryParameterObject parameter, boolean useCache) { return this.selectListWithRawParameter(statement, parameter, parameter.getFirstResult(), parameter.getMaxResults(), useCache); } public List selectListWithRawParameter(String statement, Object parameter, int firstResult, int maxResults) { return this.selectListWithRawParameter(statement, parameter, firstResult, maxResults, true); } public List selectListWithRawParameter(String statement, Object parameter, int firstResult, int maxResults, boolean useCache) { statement = this.dbSqlSessionFactory.mapStatement(statement); if (firstResult != -1 && maxResults != -1) { List loadedObjects = this.sqlSession.selectList(statement, parameter); return useCache ? this.cacheLoadOrStore(loadedObjects) : loadedObjects; } else { return Collections.EMPTY_LIST; } } public List selectListWithRawParameterWithoutFilter(String statement, Object parameter, int firstResult, int maxResults) { statement = this.dbSqlSessionFactory.mapStatement(statement); return firstResult != -1 && maxResults != -1 ? this.sqlSession.selectList(statement, parameter) : Collections.EMPTY_LIST; } public Object selectOne(String statement, Object parameter) { statement = this.dbSqlSessionFactory.mapStatement(statement); Object result = this.sqlSession.selectOne(statement, parameter); if (result instanceof Entity) { Entity loadedObject = (Entity)result; result = this.cacheLoadOrStore(loadedObject); } return result; } public T selectById(Class entityClass, String id) { return this.selectById(entityClass, id, true); } public T selectById(Class entityClass, String id, boolean useCache) { T entity = null; if (useCache) { entity = (T) this.entityCache.findInCache(entityClass, id); if (entity != null) { return entity; } } String selectStatement = this.dbSqlSessionFactory.getSelectStatement(entityClass); selectStatement = this.dbSqlSessionFactory.mapStatement(selectStatement); entity = (T) this.sqlSession.selectOne(selectStatement, id); if (entity == null) { return null; } else { this.entityCache.put(entity, true); return entity; } } protected List cacheLoadOrStore(List loadedObjects) { if (loadedObjects.isEmpty()) { return loadedObjects; } else if (!(loadedObjects.get(0) instanceof Entity)) { return loadedObjects; } else { List filteredObjects = new ArrayList(loadedObjects.size()); Iterator var3 = loadedObjects.iterator(); while(var3.hasNext()) { Object loadedObject = var3.next(); Entity cachedEntity = this.cacheLoadOrStore((Entity)loadedObject); filteredObjects.add(cachedEntity); } return filteredObjects; } } protected Entity cacheLoadOrStore(Entity entity) { Entity cachedEntity = (Entity)this.entityCache.findInCache(entity.getClass(), entity.getId()); if (cachedEntity != null) { return cachedEntity; } else { this.entityCache.put(entity, true); return entity; } } public void flush() { this.determineUpdatedObjects(); this.removeUnnecessaryOperations(); if (log.isDebugEnabled()) { this.debugFlush(); } this.flushInserts(); this.flushUpdates(); this.flushDeletes(); } protected void removeUnnecessaryOperations() { Iterator var1 = this.deletedObjects.keySet().iterator(); while(var1.hasNext()) { Class entityClass = (Class)var1.next(); Set ids = new HashSet(); Iterator entitiesToDeleteIterator = ((Map)this.deletedObjects.get(entityClass)).values().iterator(); while(entitiesToDeleteIterator.hasNext()) { Entity entityToDelete = (Entity)entitiesToDeleteIterator.next(); if (!ids.contains(entityToDelete.getId())) { ids.add(entityToDelete.getId()); } else { entitiesToDeleteIterator.remove(); } } Iterator var7 = ids.iterator(); while(var7.hasNext()) { String id = (String)var7.next(); if (this.insertedObjects.containsKey(entityClass) && ((Map)this.insertedObjects.get(entityClass)).containsKey(id)) { ((Map)this.insertedObjects.get(entityClass)).remove(id); ((Map)this.deletedObjects.get(entityClass)).remove(id); } } } } public void determineUpdatedObjects() { this.updatedObjects = new ArrayList(); Map, Map> cachedObjects = this.entityCache.getAllCachedEntities(); Iterator var2 = cachedObjects.keySet().iterator(); label34: while(var2.hasNext()) { Class clazz = (Class)var2.next(); Map classCache = (Map)cachedObjects.get(clazz); Iterator var5 = classCache.values().iterator(); while(true) { CachedEntity cachedObject; Entity cachedEntity; do { do { if (!var5.hasNext()) { continue label34; } cachedObject = (CachedEntity)var5.next(); cachedEntity = cachedObject.getEntity(); } while(this.isEntityInserted(cachedEntity)); } while(!ExecutionEntity.class.isAssignableFrom(cachedEntity.getClass()) && this.isEntityToBeDeleted(cachedEntity)); if (cachedObject.hasChanged()) { this.updatedObjects.add(cachedEntity); } } } } protected void debugFlush() { log.debug("Flushing dbSqlSession"); int nrOfInserts = 0; int nrOfUpdates = 0; int nrOfDeletes = 0; Iterator var4 = this.insertedObjects.values().iterator(); Map deletedObjectMap; Iterator var6; Entity deletedObject; while(var4.hasNext()) { deletedObjectMap = (Map)var4.next(); for(var6 = deletedObjectMap.values().iterator(); var6.hasNext(); ++nrOfInserts) { deletedObject = (Entity)var6.next(); log.debug(" insert {}", deletedObject); } } for(var4 = this.updatedObjects.iterator(); var4.hasNext(); ++nrOfUpdates) { Entity updatedObject = (Entity)var4.next(); log.debug(" update {}", updatedObject); } var4 = this.deletedObjects.values().iterator(); while(var4.hasNext()) { deletedObjectMap = (Map)var4.next(); for(var6 = deletedObjectMap.values().iterator(); var6.hasNext(); ++nrOfDeletes) { deletedObject = (Entity)var6.next(); log.debug(" delete {} with id {}", deletedObject, deletedObject.getId()); } } var4 = this.bulkDeleteOperations.values().iterator(); while(var4.hasNext()) { Collection bulkDeleteOperationList = (Collection)var4.next(); for(var6 = bulkDeleteOperationList.iterator(); var6.hasNext(); ++nrOfDeletes) { BulkDeleteOperation bulkDeleteOperation = (BulkDeleteOperation)var6.next(); log.debug(" {}", bulkDeleteOperation); } } log.debug("flush summary: {} insert, {} update, {} delete.", new Object[]{nrOfInserts, nrOfUpdates, nrOfDeletes}); log.debug("now executing flush..."); } public boolean isEntityInserted(Entity entity) { return this.insertedObjects.containsKey(entity.getClass()) && ((Map)this.insertedObjects.get(entity.getClass())).containsKey(entity.getId()); } public boolean isEntityToBeDeleted(Entity entity) { return this.deletedObjects.containsKey(entity.getClass()) && ((Map)this.deletedObjects.get(entity.getClass())).containsKey(entity.getId()); } protected void flushInserts() { if (this.insertedObjects.size() != 0) { Iterator var1 = EntityDependencyOrder.INSERT_ORDER.iterator(); Class entityClass; while(var1.hasNext()) { entityClass = (Class)var1.next(); if (this.insertedObjects.containsKey(entityClass)) { this.flushInsertEntities(entityClass, ((Map)this.insertedObjects.get(entityClass)).values()); this.insertedObjects.remove(entityClass); } } if (this.insertedObjects.size() > 0) { var1 = this.insertedObjects.keySet().iterator(); while(var1.hasNext()) { entityClass = (Class)var1.next(); this.flushInsertEntities(entityClass, ((Map)this.insertedObjects.get(entityClass)).values()); } } this.insertedObjects.clear(); } } protected void flushInsertEntities(Class entityClass, Collection entitiesToInsert) { if (entitiesToInsert.size() == 1) { this.flushRegularInsert((Entity)entitiesToInsert.iterator().next(), entityClass); } else if (Boolean.FALSE.equals(this.dbSqlSessionFactory.isBulkInsertable(entityClass))) { Iterator var3 = entitiesToInsert.iterator(); while(var3.hasNext()) { Entity entity = (Entity)var3.next(); this.flushRegularInsert(entity, entityClass); } } else { this.flushBulkInsert(entitiesToInsert, entityClass); } } protected Collection orderExecutionEntities(Map executionEntities, boolean parentBeforeChildExecution) { List result = new ArrayList(executionEntities.size()); Map childToParentExecutionMapping = new HashMap(); Map> parentToChildrenMapping = new HashMap(); Collection executionCollection = executionEntities.values(); Iterator executionIterator; ExecutionEntity currentExecutionEntity; String executionId; String parentId; for(executionIterator = executionCollection.iterator(); executionIterator.hasNext(); ((List)parentToChildrenMapping.get(parentId)).add(currentExecutionEntity)) { currentExecutionEntity = (ExecutionEntity)executionIterator.next(); parentId = currentExecutionEntity.getParentId(); executionId = currentExecutionEntity.getSuperExecutionId(); parentId = parentId != null ? parentId : executionId; childToParentExecutionMapping.put(currentExecutionEntity.getId(), parentId); if (!parentToChildrenMapping.containsKey(parentId)) { parentToChildrenMapping.put(parentId, new ArrayList()); } } Set handledExecutionIds = new HashSet(executionEntities.size()); executionIterator = executionCollection.iterator(); while(true) { do { if (!executionIterator.hasNext()) { return result; } currentExecutionEntity = (ExecutionEntity)executionIterator.next(); executionId = currentExecutionEntity.getId(); } while(handledExecutionIds.contains(executionId)); parentId = (String)childToParentExecutionMapping.get(executionId); if (parentId != null) { while(parentId != null) { String newParentId = (String)childToParentExecutionMapping.get(parentId); if (newParentId == null) { break; } parentId = newParentId; } } if (parentId == null) { parentId = executionId; } if (executionEntities.containsKey(parentId) && !handledExecutionIds.contains(parentId)) { handledExecutionIds.add(parentId); if (parentBeforeChildExecution) { result.add(executionEntities.get(parentId)); } else { result.add(0, executionEntities.get(parentId)); } } this.collectChildExecutionsForInsertion(result, parentToChildrenMapping, handledExecutionIds, parentId, parentBeforeChildExecution); } } protected void collectChildExecutionsForInsertion(List result, Map> parentToChildrenMapping, Set handledExecutionIds, String parentId, boolean parentBeforeChildExecution) { List childExecutionEntities = (List)parentToChildrenMapping.get(parentId); if (childExecutionEntities != null) { ExecutionEntity childExecutionEntity; for(Iterator var7 = childExecutionEntities.iterator(); var7.hasNext(); this.collectChildExecutionsForInsertion(result, parentToChildrenMapping, handledExecutionIds, childExecutionEntity.getId(), parentBeforeChildExecution)) { childExecutionEntity = (ExecutionEntity)var7.next(); handledExecutionIds.add(childExecutionEntity.getId()); if (parentBeforeChildExecution) { result.add(childExecutionEntity); } else { result.add(0, childExecutionEntity); } } } } protected void flushRegularInsert(Entity entity, Class clazz) { String insertStatement = this.dbSqlSessionFactory.getInsertStatement(entity); insertStatement = this.dbSqlSessionFactory.mapStatement(insertStatement); if (insertStatement == null) { throw new ActivitiException("no insert statement for " + entity.getClass() + " in the ibatis mapping files"); } else { log.debug("inserting: {}", entity); this.sqlSession.insert(insertStatement, entity); if (entity instanceof HasRevision) { this.incrementRevision(entity); } } } protected void flushBulkInsert(Collection entities, Class clazz) { String insertStatement = this.dbSqlSessionFactory.getBulkInsertStatement(clazz); insertStatement = this.dbSqlSessionFactory.mapStatement(insertStatement); if (insertStatement == null) { throw new ActivitiException("no insert statement for " + ((Entity)entities.iterator().next()).getClass() + " in the ibatis mapping files"); } else { Iterator entityIterator = entities.iterator(); Boolean hasRevision = null; while(entityIterator.hasNext()) { List subList = new ArrayList(); for(int index = 0; entityIterator.hasNext() && index < this.dbSqlSessionFactory.getMaxNrOfStatementsInBulkInsert(); ++index) { Entity entity = (Entity)entityIterator.next(); subList.add(entity); if (hasRevision == null) { hasRevision = entity instanceof HasRevision; } } this.sqlSession.insert(insertStatement, subList); } if (hasRevision != null && hasRevision) { entityIterator = entities.iterator(); while(entityIterator.hasNext()) { this.incrementRevision((Entity)entityIterator.next()); } } } } protected void incrementRevision(Entity insertedObject) { HasRevision revisionEntity = (HasRevision)insertedObject; if (revisionEntity.getRevision() == 0) { revisionEntity.setRevision(revisionEntity.getRevisionNext()); } } protected void flushUpdates() { Iterator var1 = this.updatedObjects.iterator(); while(var1.hasNext()) { Entity updatedObject = (Entity)var1.next(); String updateStatement = this.dbSqlSessionFactory.getUpdateStatement(updatedObject); updateStatement = this.dbSqlSessionFactory.mapStatement(updateStatement); if (updateStatement == null) { throw new ActivitiException("no update statement for " + updatedObject.getClass() + " in the ibatis mapping files"); } log.debug("updating: {}", updatedObject); int updatedRecords = this.sqlSession.update(updateStatement, updatedObject); if (updatedRecords == 0) { throw new ActivitiOptimisticLockingException(updatedObject + " was updated by another transaction concurrently"); } if (updatedObject instanceof HasRevision) { ((HasRevision)updatedObject).setRevision(((HasRevision)updatedObject).getRevisionNext()); } } this.updatedObjects.clear(); } protected void flushDeletes() { if (this.deletedObjects.size() != 0 || this.bulkDeleteOperations.size() != 0) { Iterator var1; Class entityClass; for(var1 = EntityDependencyOrder.DELETE_ORDER.iterator(); var1.hasNext(); this.flushBulkDeletes(entityClass)) { entityClass = (Class)var1.next(); if (this.deletedObjects.containsKey(entityClass)) { this.flushDeleteEntities(entityClass, ((Map)this.deletedObjects.get(entityClass)).values()); this.deletedObjects.remove(entityClass); } } if (this.deletedObjects.size() > 0) { var1 = this.deletedObjects.keySet().iterator(); while(var1.hasNext()) { entityClass = (Class)var1.next(); this.flushDeleteEntities(entityClass, ((Map)this.deletedObjects.get(entityClass)).values()); this.flushBulkDeletes(entityClass); } } this.deletedObjects.clear(); } } protected void flushBulkDeletes(Class entityClass) { if (this.bulkDeleteOperations.containsKey(entityClass)) { Iterator var2 = ((List)this.bulkDeleteOperations.get(entityClass)).iterator(); while(var2.hasNext()) { BulkDeleteOperation bulkDeleteOperation = (BulkDeleteOperation)var2.next(); bulkDeleteOperation.execute(this.sqlSession); } } } protected void flushDeleteEntities(Class entityClass, Collection entitiesToDelete) { Iterator var3 = entitiesToDelete.iterator(); while(var3.hasNext()) { Entity entity = (Entity)var3.next(); String deleteStatement = this.dbSqlSessionFactory.getDeleteStatement(entity.getClass()); deleteStatement = this.dbSqlSessionFactory.mapStatement(deleteStatement); if (deleteStatement == null) { throw new ActivitiException("no delete statement for " + entity.getClass() + " in the ibatis mapping files"); } if (entity instanceof HasRevision) { int nrOfRowsDeleted = this.sqlSession.delete(deleteStatement, entity); if (nrOfRowsDeleted == 0) { throw new ActivitiOptimisticLockingException(entity + " was updated by another transaction concurrently"); } } else { this.sqlSession.delete(deleteStatement, entity); } } } public void close() { this.sqlSession.close(); } public void commit() { this.sqlSession.commit(); } public void rollback() { this.sqlSession.rollback(); } public void dbSchemaCheckVersion() { try { String dbVersion = this.getDbVersion(); if (!"6.0.0.4".equals(dbVersion)) { throw new ActivitiWrongDbException("6.0.0.4", dbVersion); } String errorMessage = null; if (!this.isEngineTablePresent()) { errorMessage = this.addMissingComponent(errorMessage, "engine"); } if (this.dbSqlSessionFactory.isDbHistoryUsed() && !this.isHistoryTablePresent()) { errorMessage = this.addMissingComponent(errorMessage, "history"); } if (this.dbSqlSessionFactory.isDbIdentityUsed() && !this.isIdentityTablePresent()) { errorMessage = this.addMissingComponent(errorMessage, "identity"); } if (errorMessage != null) { throw new ActivitiException("Activiti database problem: " + errorMessage); } } catch (Exception var3) { Exception e = var3; if (this.isMissingTablesException(e)) { throw new ActivitiException("no activiti tables in db. set " + "6.0.0.4" + ")"; dbHistoryProperty.setValue(dbHistoryValue); this.dbSchemaUpgrade("engine", matchingVersionIndex); feedback = "upgraded Activiti from " + dbVersion + " to " + "6.0.0.4"; } } else { this.dbSchemaCreateEngine(); } if (this.isHistoryTablePresent()) { if (isUpgradeNeeded) { this.dbSchemaUpgrade("history", matchingVersionIndex); } } else if (this.dbSqlSessionFactory.isDbHistoryUsed()) { this.dbSchemaCreateHistory(); } if (this.isIdentityTablePresent()) { if (isUpgradeNeeded) { this.dbSchemaUpgrade("identity", matchingVersionIndex); } } else if (this.dbSqlSessionFactory.isDbIdentityUsed()) { this.dbSchemaCreateIdentity(); } return feedback; } protected int findMatchingVersionIndex(String dbVersion) { int index = 0; int matchingVersionIndex = -1; while(matchingVersionIndex < 0 && index < ACTIVITI_VERSIONS.size()) { if (((ActivitiVersion)ACTIVITI_VERSIONS.get(index)).matches(dbVersion)) { matchingVersionIndex = index; } else { ++index; } } return matchingVersionIndex; } public boolean isEngineTablePresent() { return this.isTablePresent("ACT_RU_EXECUTION"); } public boolean isHistoryTablePresent() { return this.isTablePresent("ACT_HI_PROCINST"); } public boolean isIdentityTablePresent() { return this.isTablePresent("ACT_ID_USER"); } public boolean isTablePresent(String tableName) { if (!this.dbSqlSessionFactory.isTablePrefixIsSchema()) { tableName = this.prependDatabaseTablePrefix(tableName); } Connection connection = null; try { connection = this.sqlSession.getConnection(); DatabaseMetaData databaseMetaData = connection.getMetaData(); ResultSet tables = null; String catalog = this.connectionMetadataDefaultCatalog; if (this.dbSqlSessionFactory.getDatabaseCatalog() != null && this.dbSqlSessionFactory.getDatabaseCatalog().length() > 0) { catalog = this.dbSqlSessionFactory.getDatabaseCatalog(); } String schema = this.connectionMetadataDefaultSchema; if (this.dbSqlSessionFactory.getDatabaseSchema() != null && this.dbSqlSessionFactory.getDatabaseSchema().length() > 0) { schema = this.dbSqlSessionFactory.getDatabaseSchema(); } String databaseType = this.dbSqlSessionFactory.getDatabaseType(); if ("postgres".equals(databaseType)) { tableName = tableName.toLowerCase(); } if (schema != null && "oracle".equals(databaseType)) { schema = schema.toUpperCase(); } if (catalog != null && catalog.length() == 0) { catalog = null; } boolean var8; try { tables = databaseMetaData.getTables(catalog, schema, tableName, JDBC_METADATA_TABLE_TYPES); var8 = tables.next(); } finally { try { tables.close(); } catch (Exception var16) { Exception e = var16; log.error("Error closing meta data tables", e); } } return var8; } catch (Exception var18) { Exception e = var18; throw new ActivitiException("couldn't check if tables are already present using metadata: " + e.getMessage(), e); } } protected boolean isUpgradeNeeded(String versionInDatabase) { if ("6.0.0.4".equals(versionInDatabase)) { return false; } else { String cleanDbVersion = this.getCleanVersion(versionInDatabase); String[] cleanDbVersionSplitted = cleanDbVersion.split("\\."); int dbMajorVersion = Integer.valueOf(cleanDbVersionSplitted[0]); int dbMinorVersion = Integer.valueOf(cleanDbVersionSplitted[1]); String cleanEngineVersion = this.getCleanVersion("6.0.0.4"); String[] cleanEngineVersionSplitted = cleanEngineVersion.split("\\."); int engineMajorVersion = Integer.valueOf(cleanEngineVersionSplitted[0]); int engineMinorVersion = Integer.valueOf(cleanEngineVersionSplitted[1]); if (dbMajorVersion <= engineMajorVersion && (dbMajorVersion > engineMajorVersion || dbMinorVersion <= engineMinorVersion)) { if (cleanDbVersion.compareTo(cleanEngineVersion) == 0) { log.warn("Engine-version is the same, but not an exact match: {} vs. {}. Not performing database-upgrade.", versionInDatabase, "6.0.0.4"); return false; } else { return true; } } else { throw new ActivitiException("Version of activiti database (" + versionInDatabase + ") is more recent than the engine (" + "6.0.0.4" + ")"); } } } protected String getCleanVersion(String versionString) { Matcher matcher = CLEAN_VERSION_REGEX.matcher(versionString); if (!matcher.find()) { throw new ActivitiException("Illegal format for version: " + versionString); } else { String cleanString = matcher.group(); try { Double.parseDouble(cleanString); return cleanString; } catch (NumberFormatException var5) { throw new ActivitiException("Illegal format for version: " + versionString); } } } protected String prependDatabaseTablePrefix(String tableName) { return this.dbSqlSessionFactory.getDatabaseTablePrefix() + tableName; } protected void dbSchemaUpgrade(String component, int currentDatabaseVersionsIndex) { ActivitiVersion activitiVersion = (ActivitiVersion)ACTIVITI_VERSIONS.get(currentDatabaseVersionsIndex); String dbVersion = activitiVersion.getMainVersion(); log.info("upgrading activiti {} schema from {} to {}", new Object[]{component, dbVersion, "6.0.0.4"}); for(int i = currentDatabaseVersionsIndex + 1; i < ACTIVITI_VERSIONS.size(); ++i) { String nextVersion = ((ActivitiVersion)ACTIVITI_VERSIONS.get(i)).getMainVersion(); if (nextVersion.endsWith("-SNAPSHOT")) { nextVersion = nextVersion.substring(0, nextVersion.length() - "-SNAPSHOT".length()); } dbVersion = dbVersion.replace(".", ""); nextVersion = nextVersion.replace(".", ""); log.info("Upgrade needed: {} -> {}. Looking for schema update resource for component '{}'", new Object[]{dbVersion, nextVersion, component}); this.executeSchemaResource("upgrade", component, this.getResourceForDbOperation("upgrade", "upgradestep." + dbVersion + ".to." + nextVersion, component), true); dbVersion = nextVersion; } } public String getResourceForDbOperation(String directory, String operation, String component) { String databaseType = this.dbSqlSessionFactory.getDatabaseType(); // 当databaseType 为dm时,借用oracle的sql文件来代替执行 if (ProcessEngineConfigurationImpl.DATABASE_TYPE_DM.equals(databaseType)) { databaseType = ProcessEngineConfigurationImpl.DATABASE_TYPE_ORACLE; } return "org/activiti/db/" + directory + "/activiti." + databaseType + "." + operation + "." + component + ".sql"; } public void executeSchemaResource(String operation, String component, String resourceName, boolean isOptional) { InputStream inputStream = null; try { inputStream = ReflectUtil.getResourceAsStream(resourceName); if (inputStream == null) { if (!isOptional) { throw new ActivitiException("resource '" + resourceName + "' is not available"); } log.info("no schema resource {} for {}", resourceName, operation); } else { this.executeSchemaResource(operation, component, resourceName, inputStream); } } finally { IoUtil.closeSilently(inputStream); } } private void executeSchemaResource(String operation, String component, String resourceName, InputStream inputStream) { log.info("performing {} on {} with resource {}", new Object[]{operation, component, resourceName}); String sqlStatement = null; String exceptionSqlStatement = null; try { Connection connection = this.sqlSession.getConnection(); Exception exception = null; byte[] bytes = IoUtil.readInputStream(inputStream, resourceName); String ddlStatements = new String(bytes); try { if (this.isMysql()) { DatabaseMetaData databaseMetaData = connection.getMetaData(); int majorVersion = databaseMetaData.getDatabaseMajorVersion(); int minorVersion = databaseMetaData.getDatabaseMinorVersion(); log.info("Found MySQL: majorVersion=" + majorVersion + " minorVersion=" + minorVersion); if (majorVersion <= 5 && minorVersion < 6) { ddlStatements = this.updateDdlForMySqlVersionLowerThan56(ddlStatements); } } } catch (Exception var26) { Exception e = var26; log.info("Could not get database metadata", e); } BufferedReader reader = new BufferedReader(new StringReader(ddlStatements)); String line = this.readNextTrimmedLine(reader); for(boolean inOraclePlsqlBlock = false; line != null; line = this.readNextTrimmedLine(reader)) { if (line.startsWith("# ")) { log.debug(line.substring(2)); } else if (line.startsWith("-- ")) { log.debug(line.substring(3)); } else { Exception e; if (line.startsWith("execute java ")) { String upgradestepClassName = line.substring(13).trim(); e = null; DbUpgradeStep dbUpgradeStep; try { dbUpgradeStep = (DbUpgradeStep)ReflectUtil.instantiate(upgradestepClassName); } catch (ActivitiException var25) { ActivitiException ex = var25; throw new ActivitiException("database update java class '" + upgradestepClassName + "' can't be instantiated: " + ex.getMessage(), ex); } try { log.debug("executing upgrade step java class {}", upgradestepClassName); dbUpgradeStep.execute(this); } catch (Exception var24) { Exception ex = var24; throw new ActivitiException("error while executing database update java class '" + upgradestepClassName + "': " + ex.getMessage(), ex); } } else if (line.length() > 0) { if (this.isOracle() && line.startsWith("begin")) { inOraclePlsqlBlock = true; sqlStatement = this.addSqlStatementPiece(sqlStatement, line); } else if ((!line.endsWith(";") || inOraclePlsqlBlock) && (!line.startsWith("/") || !inOraclePlsqlBlock)) { sqlStatement = this.addSqlStatementPiece(sqlStatement, line); } else { if (inOraclePlsqlBlock) { inOraclePlsqlBlock = false; } else { sqlStatement = this.addSqlStatementPiece(sqlStatement, line.substring(0, line.length() - 1)); } Statement jdbcStatement = connection.createStatement(); try { log.debug("SQL: {}", sqlStatement); jdbcStatement.execute(sqlStatement); jdbcStatement.close(); } catch (Exception var27) { e = var27; if (exception == null) { exception = e; } log.error("problem during schema {}, statement {}", new Object[]{operation, sqlStatement, e}); } finally { sqlStatement = null; } } } } } if (exception != null) { throw exception; } else { log.debug("activiti db schema {} for component {} successful", operation, component); } } catch (Exception var29) { Exception e = var29; throw new ActivitiException("couldn't " + operation + " db schema: " + exceptionSqlStatement, e); } } protected String updateDdlForMySqlVersionLowerThan56(String ddlStatements) { return ddlStatements.replace("timestamp(3)", "timestamp").replace("datetime(3)", "datetime").replace("TIMESTAMP(3)", "TIMESTAMP").replace("DATETIME(3)", "DATETIME"); } protected String addSqlStatementPiece(String sqlStatement, String line) { return sqlStatement == null ? line : sqlStatement + " \n" + line; } protected String readNextTrimmedLine(BufferedReader reader) throws IOException { String line = reader.readLine(); if (line != null) { line = line.trim(); } return line; } protected boolean isMissingTablesException(Exception e) { String exceptionMessage = e.getMessage(); if (e.getMessage() != null) { if (exceptionMessage.indexOf("Table") != -1 && exceptionMessage.indexOf("not found") != -1) { return true; } if ((exceptionMessage.indexOf("Table") != -1 || exceptionMessage.indexOf("table") != -1) && exceptionMessage.indexOf("doesn't exist") != -1) { return true; } if ((exceptionMessage.indexOf("relation") != -1 || exceptionMessage.indexOf("table") != -1) && exceptionMessage.indexOf("does not exist") != -1) { return true; } } return false; } public void performSchemaOperationsProcessEngineBuild() { String databaseSchemaUpdate = Context.getProcessEngineConfiguration().getDatabaseSchemaUpdate(); log.debug("Executing performSchemaOperationsProcessEngineBuild with setting " + databaseSchemaUpdate); if ("drop-create".equals(databaseSchemaUpdate)) { try { this.dbSchemaDrop(); } catch (RuntimeException var3) { } } if (!"create-drop".equals(databaseSchemaUpdate) && !"drop-create".equals(databaseSchemaUpdate) && !"create".equals(databaseSchemaUpdate)) { if ("false".equals(databaseSchemaUpdate)) { this.dbSchemaCheckVersion(); } else if ("true".equals(databaseSchemaUpdate)) { this.dbSchemaUpdate(); } } else { this.dbSchemaCreate(); } } public void performSchemaOperationsProcessEngineClose() { String databaseSchemaUpdate = Context.getProcessEngineConfiguration().getDatabaseSchemaUpdate(); if ("create-drop".equals(databaseSchemaUpdate)) { this.dbSchemaDrop(); } } public T getCustomMapper(Class type) { return this.sqlSession.getMapper(type); } public boolean isMysql() { return this.dbSqlSessionFactory.getDatabaseType().equals("mysql"); } public boolean isOracle() { return this.dbSqlSessionFactory.getDatabaseType().equals("oracle"); } public DeploymentQueryImpl createDeploymentQuery() { return new DeploymentQueryImpl(); } public ModelQueryImpl createModelQueryImpl() { return new ModelQueryImpl(); } public ProcessDefinitionQueryImpl createProcessDefinitionQuery() { return new ProcessDefinitionQueryImpl(); } public ProcessInstanceQueryImpl createProcessInstanceQuery() { return new ProcessInstanceQueryImpl(); } public ExecutionQueryImpl createExecutionQuery() { return new ExecutionQueryImpl(); } public TaskQueryImpl createTaskQuery() { return new TaskQueryImpl(); } public JobQueryImpl createJobQuery() { return new JobQueryImpl(); } public HistoricProcessInstanceQueryImpl createHistoricProcessInstanceQuery() { return new HistoricProcessInstanceQueryImpl(); } public HistoricActivityInstanceQueryImpl createHistoricActivityInstanceQuery() { return new HistoricActivityInstanceQueryImpl(); } public HistoricTaskInstanceQueryImpl createHistoricTaskInstanceQuery() { return new HistoricTaskInstanceQueryImpl(); } public HistoricDetailQueryImpl createHistoricDetailQuery() { return new HistoricDetailQueryImpl(); } public HistoricVariableInstanceQueryImpl createHistoricVariableInstanceQuery() { return new HistoricVariableInstanceQueryImpl(); } public UserQueryImpl createUserQuery() { return new UserQueryImpl(); } public GroupQueryImpl createGroupQuery() { return new GroupQueryImpl(); } public SqlSession getSqlSession() { return this.sqlSession; } public DbSqlSessionFactory getDbSqlSessionFactory() { return this.dbSqlSessionFactory; } static { 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")); 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")); ACTIVITI_VERSIONS.add(new ActivitiVersion("5.18.0.0")); ACTIVITI_VERSIONS.add(new ActivitiVersion("5.18.0.1")); ACTIVITI_VERSIONS.add(new ActivitiVersion("5.20.0.0")); ACTIVITI_VERSIONS.add(new ActivitiVersion("5.20.0.1")); ACTIVITI_VERSIONS.add(new ActivitiVersion("5.20.0.2")); ACTIVITI_VERSIONS.add(new ActivitiVersion("5.21.0.0")); ACTIVITI_VERSIONS.add(new ActivitiVersion("5.22.0.0")); ACTIVITI_VERSIONS.add(new ActivitiVersion("5.99.0.0")); ACTIVITI_VERSIONS.add(new ActivitiVersion("6.0.0.0")); ACTIVITI_VERSIONS.add(new ActivitiVersion("6.0.0.1")); ACTIVITI_VERSIONS.add(new ActivitiVersion("6.0.0.2")); ACTIVITI_VERSIONS.add(new ActivitiVersion("6.0.0.3")); ACTIVITI_VERSIONS.add(new ActivitiVersion("6.0.0.4")); JDBC_METADATA_TABLE_TYPES = new String[]{"TABLE"}; } }