TSK-986: Extract DbproductName and DbproductId
This commit is contained in:
parent
67a67388f1
commit
0d24a29f68
|
|
@ -0,0 +1,46 @@
|
||||||
|
package pro.taskana.configuration;
|
||||||
|
|
||||||
|
import pro.taskana.exceptions.UnsupportedDatabaseException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported versions of databases.
|
||||||
|
*/
|
||||||
|
public enum DB {
|
||||||
|
|
||||||
|
H2("H2", "h2"),
|
||||||
|
DB2("DB2", "db2"),
|
||||||
|
POSTGRESS("PostgreSQL", "postgres");
|
||||||
|
|
||||||
|
public final String dbProductname;
|
||||||
|
public final String dbProductId;
|
||||||
|
|
||||||
|
DB(String dbProductname, String dbProductId) {
|
||||||
|
this.dbProductname = dbProductname;
|
||||||
|
this.dbProductId = dbProductId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isDb2(String dbProductName) {
|
||||||
|
return dbProductName.contains(DB2.dbProductname);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isH2(String databaseProductName) {
|
||||||
|
return databaseProductName.contains(H2.dbProductname);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPostgreSQL(String databaseProductName) {
|
||||||
|
return POSTGRESS.dbProductname.equals(databaseProductName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDatabaseProductId(String databaseProductName) {
|
||||||
|
|
||||||
|
if (isDb2(databaseProductName)) {
|
||||||
|
return DB2.dbProductId;
|
||||||
|
} else if (isH2(databaseProductName)) {
|
||||||
|
return H2.dbProductId;
|
||||||
|
} else if (isPostgreSQL(databaseProductName)) {
|
||||||
|
return POSTGRESS.dbProductId;
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedDatabaseException(databaseProductName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -44,13 +44,13 @@ public class DbSchemaCreator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String selectDbScriptFileName(String dbProductName) {
|
private static String selectDbScriptFileName(String dbProductName) {
|
||||||
return "PostgreSQL".equals(dbProductName)
|
return DB.isPostgreSQL(dbProductName)
|
||||||
? DB_SCHEMA_POSTGRES
|
? DB_SCHEMA_POSTGRES
|
||||||
: "H2".equals(dbProductName) ? DB_SCHEMA : DB_SCHEMA_DB2;
|
: DB.isH2(dbProductName) ? DB_SCHEMA : DB_SCHEMA_DB2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String selectDbSchemaDetectionScript(String dbProductName) {
|
private static String selectDbSchemaDetectionScript(String dbProductName) {
|
||||||
return "PostgreSQL".equals(dbProductName) ? DB_SCHEMA_DETECTION_POSTGRES : DB_SCHEMA_DETECTION;
|
return DB.isPostgreSQL(dbProductName) ? DB_SCHEMA_DETECTION_POSTGRES : DB_SCHEMA_DETECTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,7 @@ public class TaskanaEngineConfiguration {
|
||||||
|
|
||||||
try (Connection connection = dataSource.getConnection()) {
|
try (Connection connection = dataSource.getConnection()) {
|
||||||
String databaseProductName = connection.getMetaData().getDatabaseProductName();
|
String databaseProductName = connection.getMetaData().getDatabaseProductName();
|
||||||
if (TaskanaEngineImpl.isPostgreSQL(databaseProductName)) {
|
if (DB.isPostgreSQL(databaseProductName)) {
|
||||||
this.schemaName = this.schemaName.toLowerCase();
|
this.schemaName = this.schemaName.toLowerCase();
|
||||||
} else {
|
} else {
|
||||||
this.schemaName = this.schemaName.toUpperCase();
|
this.schemaName = this.schemaName.toUpperCase();
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
package pro.taskana.exceptions;
|
package pro.taskana.exceptions;
|
||||||
|
|
||||||
import pro.taskana.security.CurrentUserContext;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This exception is used to communicate a not authorized user.
|
* This exception is used to communicate a not authorized user.
|
||||||
*/
|
*/
|
||||||
public class NotAuthorizedException extends TaskanaException {
|
public class NotAuthorizedException extends TaskanaException {
|
||||||
|
|
||||||
public NotAuthorizedException(String msg) {
|
private final String currentUserId;
|
||||||
super(msg + " - [CURRENT USER: {'" + CurrentUserContext.getUserid() + "'}]");
|
|
||||||
|
public NotAuthorizedException(String msg, String currentUserId) {
|
||||||
|
super(msg + " - [CURRENT USER: {'" + currentUserId + "'}]");
|
||||||
|
this.currentUserId = currentUserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCurrentUserId() {
|
||||||
|
return currentUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final long serialVersionUID = 21235L;
|
private static final long serialVersionUID = 21235L;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import pro.taskana.TaskSummary;
|
||||||
import pro.taskana.TaskanaRole;
|
import pro.taskana.TaskanaRole;
|
||||||
import pro.taskana.TimeInterval;
|
import pro.taskana.TimeInterval;
|
||||||
import pro.taskana.WorkbasketPermission;
|
import pro.taskana.WorkbasketPermission;
|
||||||
|
import pro.taskana.configuration.DB;
|
||||||
import pro.taskana.exceptions.InvalidArgumentException;
|
import pro.taskana.exceptions.InvalidArgumentException;
|
||||||
import pro.taskana.exceptions.NotAuthorizedException;
|
import pro.taskana.exceptions.NotAuthorizedException;
|
||||||
import pro.taskana.exceptions.NotAuthorizedToQueryWorkbasketException;
|
import pro.taskana.exceptions.NotAuthorizedToQueryWorkbasketException;
|
||||||
|
|
@ -706,23 +707,27 @@ public class TaskQueryImpl implements TaskQuery {
|
||||||
public TaskQuery orderByClassificationName(SortDirection sortDirection) {
|
public TaskQuery orderByClassificationName(SortDirection sortDirection) {
|
||||||
joinWithClassifications = true;
|
joinWithClassifications = true;
|
||||||
addClassificationNameToSelectClauseForOrdering = true;
|
addClassificationNameToSelectClauseForOrdering = true;
|
||||||
return this.taskanaEngine.getSqlSession().getConfiguration().getDatabaseId().equals("db2")
|
return DB.DB2.dbProductId.equals(getDatabaseId())
|
||||||
? addOrderCriteria("CNAME", sortDirection)
|
? addOrderCriteria("CNAME", sortDirection)
|
||||||
: addOrderCriteria("c.NAME", sortDirection);
|
: addOrderCriteria("c.NAME", sortDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getDatabaseId() {
|
||||||
|
return this.taskanaEngine.getSqlSession().getConfiguration().getDatabaseId();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TaskQuery orderByAttachmentClassificationName(SortDirection sortDirection) {
|
public TaskQuery orderByAttachmentClassificationName(SortDirection sortDirection) {
|
||||||
joinWithAttachments = true;
|
joinWithAttachments = true;
|
||||||
addAttachmentClassificationNameToSelectClauseForOrdering = true;
|
addAttachmentClassificationNameToSelectClauseForOrdering = true;
|
||||||
return this.taskanaEngine.getSqlSession().getConfiguration().getDatabaseId().equals("db2")
|
return DB.DB2.dbProductId.equals(getDatabaseId())
|
||||||
? addOrderCriteria("ACNAME", sortDirection)
|
? addOrderCriteria("ACNAME", sortDirection)
|
||||||
: addOrderCriteria("ac.NAME", sortDirection);
|
: addOrderCriteria("ac.NAME", sortDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TaskQuery orderByClassificationKey(SortDirection sortDirection) {
|
public TaskQuery orderByClassificationKey(SortDirection sortDirection) {
|
||||||
return this.taskanaEngine.getSqlSession().getConfiguration().getDatabaseId().equals("db2")
|
return DB.DB2.dbProductId.equals(getDatabaseId())
|
||||||
? addOrderCriteria("TCLASSIFICATION_KEY", sortDirection)
|
? addOrderCriteria("TCLASSIFICATION_KEY", sortDirection)
|
||||||
: addOrderCriteria("t.CLASSIFICATION_KEY", sortDirection);
|
: addOrderCriteria("t.CLASSIFICATION_KEY", sortDirection);
|
||||||
}
|
}
|
||||||
|
|
@ -811,7 +816,7 @@ public class TaskQueryImpl implements TaskQuery {
|
||||||
public TaskQuery orderByAttachmentClassificationKey(SortDirection sortDirection) {
|
public TaskQuery orderByAttachmentClassificationKey(SortDirection sortDirection) {
|
||||||
joinWithAttachments = true;
|
joinWithAttachments = true;
|
||||||
addAttachmentColumnsToSelectClauseForOrdering = true;
|
addAttachmentColumnsToSelectClauseForOrdering = true;
|
||||||
return this.taskanaEngine.getSqlSession().getConfiguration().getDatabaseId().equals("db2")
|
return DB.DB2.dbProductId.equals(getDatabaseId())
|
||||||
? addOrderCriteria("ACLASSIFICATION_KEY", sortDirection)
|
? addOrderCriteria("ACLASSIFICATION_KEY", sortDirection)
|
||||||
: addOrderCriteria("a.CLASSIFICATION_KEY", sortDirection);
|
: addOrderCriteria("a.CLASSIFICATION_KEY", sortDirection);
|
||||||
}
|
}
|
||||||
|
|
@ -820,7 +825,7 @@ public class TaskQueryImpl implements TaskQuery {
|
||||||
public TaskQuery orderByAttachmentClassificationId(SortDirection sortDirection) {
|
public TaskQuery orderByAttachmentClassificationId(SortDirection sortDirection) {
|
||||||
joinWithAttachments = true;
|
joinWithAttachments = true;
|
||||||
addAttachmentColumnsToSelectClauseForOrdering = true;
|
addAttachmentColumnsToSelectClauseForOrdering = true;
|
||||||
return this.taskanaEngine.getSqlSession().getConfiguration().getDatabaseId().equals("db2")
|
return DB.DB2.dbProductId.equals(getDatabaseId())
|
||||||
? addOrderCriteria("ACLASSIFICATION_ID", sortDirection)
|
? addOrderCriteria("ACLASSIFICATION_ID", sortDirection)
|
||||||
: addOrderCriteria("a.CLASSIFICATION_ID", sortDirection);
|
: addOrderCriteria("a.CLASSIFICATION_ID", sortDirection);
|
||||||
}
|
}
|
||||||
|
|
@ -984,15 +989,13 @@ public class TaskQueryImpl implements TaskQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLinkToMapperScript() {
|
public String getLinkToMapperScript() {
|
||||||
return this.taskanaEngine
|
return DB.DB2.dbProductId.equals(getDatabaseId())
|
||||||
.getSqlSession()
|
|
||||||
.getConfiguration().getDatabaseId().equals("db2")
|
|
||||||
? LINK_TO_MAPPER_DB2
|
? LINK_TO_MAPPER_DB2
|
||||||
: LINK_TO_MAPPER;
|
: LINK_TO_MAPPER;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLinkToCounterTaskScript() {
|
public String getLinkToCounterTaskScript() {
|
||||||
return this.taskanaEngine.getSqlSession().getConfiguration().getDatabaseId().equals("db2")
|
return DB.DB2.dbProductId.equals(getDatabaseId())
|
||||||
? LINK_TO_COUNTER_DB2
|
? LINK_TO_COUNTER_DB2
|
||||||
: LINK_TO_COUNTER;
|
: LINK_TO_COUNTER;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -277,7 +277,8 @@ public class TaskServiceImpl implements TaskService {
|
||||||
if (workbaskets.isEmpty()) {
|
if (workbaskets.isEmpty()) {
|
||||||
String currentUser = CurrentUserContext.getUserid();
|
String currentUser = CurrentUserContext.getUserid();
|
||||||
throw new NotAuthorizedException(
|
throw new NotAuthorizedException(
|
||||||
"The current user " + currentUser + " has no read permission for workbasket " + workbasketId);
|
"The current user " + currentUser + " has no read permission for workbasket " + workbasketId,
|
||||||
|
CurrentUserContext.getUserid());
|
||||||
} else {
|
} else {
|
||||||
resultTask.setWorkbasketSummary(workbaskets.get(0));
|
resultTask.setWorkbasketSummary(workbaskets.get(0));
|
||||||
}
|
}
|
||||||
|
|
@ -442,7 +443,8 @@ public class TaskServiceImpl implements TaskService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BulkOperationResults<String, TaskanaException> setCallbackStateForTasks(List<String> externalIds, CallbackState state) {
|
public BulkOperationResults<String, TaskanaException> setCallbackStateForTasks(List<String> externalIds,
|
||||||
|
CallbackState state) {
|
||||||
if (LOGGER.isDebugEnabled()) {
|
if (LOGGER.isDebugEnabled()) {
|
||||||
LOGGER.debug("entry to setCallbackStateForTasks(externalIds = {})", LoggerUtils.listToString(externalIds));
|
LOGGER.debug("entry to setCallbackStateForTasks(externalIds = {})", LoggerUtils.listToString(externalIds));
|
||||||
}
|
}
|
||||||
|
|
@ -502,7 +504,6 @@ public class TaskServiceImpl implements TaskService {
|
||||||
LOGGER.debug("exit from removeSingleTask()");
|
LOGGER.debug("exit from removeSingleTask()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void removeSingleTaskForCallbackStateByExternalId(BulkOperationResults<String,
|
private void removeSingleTaskForCallbackStateByExternalId(BulkOperationResults<String,
|
||||||
TaskanaException> bulkLog,
|
TaskanaException> bulkLog,
|
||||||
List<MinimalTaskSummary> taskSummaries, Iterator<String> externalIdIterator, CallbackState desiredCallbackState) {
|
List<MinimalTaskSummary> taskSummaries, Iterator<String> externalIdIterator, CallbackState desiredCallbackState) {
|
||||||
|
|
@ -1737,7 +1738,8 @@ public class TaskServiceImpl implements TaskService {
|
||||||
throw new InvalidStateException("Cannot delete Task " + taskId + " because it is not completed.");
|
throw new InvalidStateException("Cannot delete Task " + taskId + " because it is not completed.");
|
||||||
}
|
}
|
||||||
if (CallbackState.CALLBACK_PROCESSING_REQUIRED.equals(task.getCallbackState())) {
|
if (CallbackState.CALLBACK_PROCESSING_REQUIRED.equals(task.getCallbackState())) {
|
||||||
throw new InvalidStateException("Task " + taskId + " cannot be deleted because its callback is not yet processed");
|
throw new InvalidStateException(
|
||||||
|
"Task " + taskId + " cannot be deleted because its callback is not yet processed");
|
||||||
}
|
}
|
||||||
|
|
||||||
taskMapper.delete(taskId);
|
taskMapper.delete(taskId);
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,13 @@ import pro.taskana.history.HistoryEventProducer;
|
||||||
import pro.taskana.history.events.task.TransferredEvent;
|
import pro.taskana.history.events.task.TransferredEvent;
|
||||||
import pro.taskana.impl.util.LoggerUtils;
|
import pro.taskana.impl.util.LoggerUtils;
|
||||||
import pro.taskana.mappings.TaskMapper;
|
import pro.taskana.mappings.TaskMapper;
|
||||||
|
import pro.taskana.security.CurrentUserContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is responsible for the transfer of tasks.
|
* This class is responsible for the transfer of tasks.
|
||||||
*/
|
*/
|
||||||
public class TaskTransferrer {
|
public class TaskTransferrer {
|
||||||
|
|
||||||
private static final String WAS_NOT_FOUND2 = " was not found.";
|
private static final String WAS_NOT_FOUND2 = " was not found.";
|
||||||
private static final String CANNOT_BE_TRANSFERRED = " cannot be transferred.";
|
private static final String CANNOT_BE_TRANSFERRED = " cannot be transferred.";
|
||||||
private static final String COMPLETED_TASK_WITH_ID = "Completed task with id ";
|
private static final String COMPLETED_TASK_WITH_ID = "Completed task with id ";
|
||||||
|
|
@ -305,7 +307,8 @@ public class TaskTransferrer {
|
||||||
.noneMatch(wb -> taskSummary.getWorkbasketId().equals(wb.getId()))) {
|
.noneMatch(wb -> taskSummary.getWorkbasketId().equals(wb.getId()))) {
|
||||||
bulkLog.addError(currentTaskId,
|
bulkLog.addError(currentTaskId,
|
||||||
new NotAuthorizedException(
|
new NotAuthorizedException(
|
||||||
"The workbasket of this task got not TRANSFER permissions. TaskId=" + currentTaskId));
|
"The workbasket of this task got not TRANSFER permissions. TaskId=" + currentTaskId,
|
||||||
|
CurrentUserContext.getUserid()));
|
||||||
taskIdIterator.remove();
|
taskIdIterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,12 @@ import pro.taskana.TaskService;
|
||||||
import pro.taskana.TaskanaEngine;
|
import pro.taskana.TaskanaEngine;
|
||||||
import pro.taskana.TaskanaRole;
|
import pro.taskana.TaskanaRole;
|
||||||
import pro.taskana.WorkbasketService;
|
import pro.taskana.WorkbasketService;
|
||||||
|
import pro.taskana.configuration.DB;
|
||||||
import pro.taskana.configuration.TaskanaEngineConfiguration;
|
import pro.taskana.configuration.TaskanaEngineConfiguration;
|
||||||
import pro.taskana.exceptions.AutocommitFailedException;
|
import pro.taskana.exceptions.AutocommitFailedException;
|
||||||
import pro.taskana.exceptions.ConnectionNotSetException;
|
import pro.taskana.exceptions.ConnectionNotSetException;
|
||||||
import pro.taskana.exceptions.NotAuthorizedException;
|
import pro.taskana.exceptions.NotAuthorizedException;
|
||||||
import pro.taskana.exceptions.SystemException;
|
import pro.taskana.exceptions.SystemException;
|
||||||
import pro.taskana.exceptions.UnsupportedDatabaseException;
|
|
||||||
import pro.taskana.history.HistoryEventProducer;
|
import pro.taskana.history.HistoryEventProducer;
|
||||||
import pro.taskana.impl.persistence.MapTypeHandler;
|
import pro.taskana.impl.persistence.MapTypeHandler;
|
||||||
import pro.taskana.impl.util.LoggerUtils;
|
import pro.taskana.impl.util.LoggerUtils;
|
||||||
|
|
@ -58,7 +58,7 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
|
|
||||||
private static final String DEFAULT = "default";
|
private static final String DEFAULT = "default";
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(TaskanaEngineImpl.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(TaskanaEngineImpl.class);
|
||||||
private static ThreadLocal<Deque<SqlSessionManager>> sessionStack = new ThreadLocal<>();
|
private static SessionStack sessionStack = new SessionStack();
|
||||||
protected TaskanaEngineConfiguration taskanaEngineConfiguration;
|
protected TaskanaEngineConfiguration taskanaEngineConfiguration;
|
||||||
protected TransactionFactory transactionFactory;
|
protected TransactionFactory transactionFactory;
|
||||||
protected SqlSessionManager sessionManager;
|
protected SqlSessionManager sessionManager;
|
||||||
|
|
@ -81,58 +81,6 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
return new TaskanaEngineImpl(taskanaEngineConfiguration);
|
return new TaskanaEngineImpl(taskanaEngineConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* With sessionStack, we maintain a Stack of SqlSessionManager objects on a per thread basis. SqlSessionManager is
|
|
||||||
* the MyBatis object that wraps database connections. The purpose of this stack is to keep track of nested calls.
|
|
||||||
* Each external API call is wrapped into taskanaEngineImpl.openConnection(); .....
|
|
||||||
* taskanaEngineImpl.returnConnection(); calls. In order to avoid duplicate opening / closing of connections, we use
|
|
||||||
* the sessionStack in the following way: Each time, an openConnection call is received, we push the current
|
|
||||||
* sessionManager onto the stack. On the first call to openConnection, we call sessionManager.startManagedSession()
|
|
||||||
* to open a database connection. On each call to returnConnection() we pop one instance of sessionManager from the
|
|
||||||
* stack. When the stack becomes empty, we close the database connection by calling sessionManager.close()
|
|
||||||
*
|
|
||||||
* @return Stack of SqlSessionManager
|
|
||||||
*/
|
|
||||||
private static Deque<SqlSessionManager> getSessionStack() {
|
|
||||||
Deque<SqlSessionManager> stack = sessionStack.get();
|
|
||||||
if (stack == null) {
|
|
||||||
stack = new ArrayDeque<>();
|
|
||||||
sessionStack.set(stack);
|
|
||||||
}
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static SqlSessionManager getSessionFromStack() {
|
|
||||||
Deque<SqlSessionManager> stack = getSessionStack();
|
|
||||||
if (stack.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return stack.peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void pushSessionToStack(SqlSessionManager session) {
|
|
||||||
getSessionStack().push(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void popSessionFromStack() {
|
|
||||||
Deque<SqlSessionManager> stack = getSessionStack();
|
|
||||||
if (!stack.isEmpty()) {
|
|
||||||
stack.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isDb2(String dbProductName) {
|
|
||||||
return dbProductName.contains("DB2");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isH2(String databaseProductName) {
|
|
||||||
return databaseProductName.contains("H2");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isPostgreSQL(String databaseProductName) {
|
|
||||||
return "PostgreSQL".equals(databaseProductName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TaskService getTaskService() {
|
public TaskService getTaskService() {
|
||||||
SqlSession session = this.sessionManager;
|
SqlSession session = this.sessionManager;
|
||||||
|
|
@ -226,7 +174,8 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
accessIds,
|
accessIds,
|
||||||
rolesAsString);
|
rolesAsString);
|
||||||
}
|
}
|
||||||
throw new NotAuthorizedException("current user is not member of role(s) " + Arrays.toString(roles));
|
throw new NotAuthorizedException("current user is not member of role(s) " + Arrays.toString(roles),
|
||||||
|
CurrentUserContext.getUserid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,15 +214,8 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
String databaseProductName;
|
String databaseProductName;
|
||||||
try (Connection con = taskanaEngineConfiguration.getDatasource().getConnection()) {
|
try (Connection con = taskanaEngineConfiguration.getDatasource().getConnection()) {
|
||||||
databaseProductName = con.getMetaData().getDatabaseProductName();
|
databaseProductName = con.getMetaData().getDatabaseProductName();
|
||||||
if (isDb2(databaseProductName)) {
|
String databaseProductId = DB.getDatabaseProductId(databaseProductName);
|
||||||
configuration.setDatabaseId("db2");
|
configuration.setDatabaseId(databaseProductId);
|
||||||
} else if (isH2(databaseProductName)) {
|
|
||||||
configuration.setDatabaseId("h2");
|
|
||||||
} else if (isPostgreSQL(databaseProductName)) {
|
|
||||||
configuration.setDatabaseId("postgres");
|
|
||||||
} else {
|
|
||||||
throw new UnsupportedDatabaseException(databaseProductName);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new SystemException(
|
throw new SystemException(
|
||||||
|
|
@ -326,7 +268,7 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
e.getCause());
|
e.getCause());
|
||||||
}
|
}
|
||||||
if (mode != ConnectionManagementMode.EXPLICIT) {
|
if (mode != ConnectionManagementMode.EXPLICIT) {
|
||||||
pushSessionToStack(sessionManager);
|
sessionStack.pushSessionToStack(sessionManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -342,8 +284,8 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
@Override
|
@Override
|
||||||
public void returnConnection() {
|
public void returnConnection() {
|
||||||
if (mode != ConnectionManagementMode.EXPLICIT) {
|
if (mode != ConnectionManagementMode.EXPLICIT) {
|
||||||
popSessionFromStack();
|
sessionStack.popSessionFromStack();
|
||||||
if (getSessionStack().isEmpty()
|
if (sessionStack.getSessionStack().isEmpty()
|
||||||
&& sessionManager != null && sessionManager.isManagedSessionStarted()) {
|
&& sessionManager != null && sessionManager.isManagedSessionStarted()) {
|
||||||
if (mode == ConnectionManagementMode.AUTOCOMMIT) {
|
if (mode == ConnectionManagementMode.AUTOCOMMIT) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -394,4 +336,51 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* With sessionStack, we maintain a Stack of SqlSessionManager objects on a per thread basis. SqlSessionManager is
|
||||||
|
* the MyBatis object that wraps database connections. The purpose of this stack is to keep track of nested calls.
|
||||||
|
* Each external API call is wrapped into taskanaEngineImpl.openConnection(); .....
|
||||||
|
* taskanaEngineImpl.returnConnection(); calls. In order to avoid duplicate opening / closing of connections, we use
|
||||||
|
* the sessionStack in the following way: Each time, an openConnection call is received, we push the current
|
||||||
|
* sessionManager onto the stack. On the first call to openConnection, we call sessionManager.startManagedSession()
|
||||||
|
* to open a database connection. On each call to returnConnection() we pop one instance of sessionManager from the
|
||||||
|
* stack. When the stack becomes empty, we close the database connection by calling sessionManager.close().
|
||||||
|
*/
|
||||||
|
private static class SessionStack {
|
||||||
|
|
||||||
|
private ThreadLocal<Deque<SqlSessionManager>> sessionStack = new ThreadLocal<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return Stack of SqlSessionManager
|
||||||
|
*/
|
||||||
|
private Deque<SqlSessionManager> getSessionStack() {
|
||||||
|
Deque<SqlSessionManager> stack = sessionStack.get();
|
||||||
|
if (stack == null) {
|
||||||
|
stack = new ArrayDeque<>();
|
||||||
|
sessionStack.set(stack);
|
||||||
|
}
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqlSessionManager getSessionFromStack() {
|
||||||
|
Deque<SqlSessionManager> stack = getSessionStack();
|
||||||
|
if (stack.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return stack.peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushSessionToStack(SqlSessionManager session) {
|
||||||
|
getSessionStack().push(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void popSessionFromStack() {
|
||||||
|
Deque<SqlSessionManager> stack = getSessionStack();
|
||||||
|
if (!stack.isEmpty()) {
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,7 @@ public class WorkbasketServiceImpl implements WorkbasketService {
|
||||||
throw new NotAuthorizedException(
|
throw new NotAuthorizedException(
|
||||||
"Not authorized. Permission '" + Arrays.toString(requestedPermissions) + "' on workbasket '"
|
"Not authorized. Permission '" + Arrays.toString(requestedPermissions) + "' on workbasket '"
|
||||||
+ workbasketId
|
+ workbasketId
|
||||||
+ "' is needed.");
|
+ "' is needed.", CurrentUserContext.getUserid());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<WorkbasketPermission> grantedPermissions = this.getPermissionsFromWorkbasketAccessItem(wbAcc);
|
List<WorkbasketPermission> grantedPermissions = this.getPermissionsFromWorkbasketAccessItem(wbAcc);
|
||||||
|
|
@ -296,7 +296,7 @@ public class WorkbasketServiceImpl implements WorkbasketService {
|
||||||
isAuthorized = false;
|
isAuthorized = false;
|
||||||
throw new NotAuthorizedException(
|
throw new NotAuthorizedException(
|
||||||
"Not authorized. Permission '" + perm.name() + "' on workbasket '" + workbasketId
|
"Not authorized. Permission '" + perm.name() + "' on workbasket '" + workbasketId
|
||||||
+ "' is needed.");
|
+ "' is needed.", CurrentUserContext.getUserid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -328,7 +328,7 @@ public class WorkbasketServiceImpl implements WorkbasketService {
|
||||||
"Not authorized. Permission '" + Arrays.toString(requestedPermissions)
|
"Not authorized. Permission '" + Arrays.toString(requestedPermissions)
|
||||||
+ "' on workbasket with key '"
|
+ "' on workbasket with key '"
|
||||||
+ workbasketKey
|
+ workbasketKey
|
||||||
+ "' and domain '" + domain + "' is needed.");
|
+ "' and domain '" + domain + "' is needed.", CurrentUserContext.getUserid());
|
||||||
}
|
}
|
||||||
List<WorkbasketPermission> grantedPermissions = this.getPermissionsFromWorkbasketAccessItem(wbAcc);
|
List<WorkbasketPermission> grantedPermissions = this.getPermissionsFromWorkbasketAccessItem(wbAcc);
|
||||||
|
|
||||||
|
|
@ -337,7 +337,7 @@ public class WorkbasketServiceImpl implements WorkbasketService {
|
||||||
isAuthorized = false;
|
isAuthorized = false;
|
||||||
throw new NotAuthorizedException(
|
throw new NotAuthorizedException(
|
||||||
"Not authorized. Permission '" + perm.name() + "' on workbasket with key '" + workbasketKey
|
"Not authorized. Permission '" + perm.name() + "' on workbasket with key '" + workbasketKey
|
||||||
+ "' and domain '" + domain + "' is needed.");
|
+ "' and domain '" + domain + "' is needed.", CurrentUserContext.getUserid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,14 @@ class ArchitectureTest {
|
||||||
myRule.check(importedClasses);
|
myRule.check(importedClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void onlyExceptionsShouldResideInExceptionPackage() {
|
||||||
|
ArchRule myRule = classes()
|
||||||
|
.that().resideInAPackage("..exceptions")
|
||||||
|
.should().beAssignableTo(Throwable.class);
|
||||||
|
myRule.check(importedClasses);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled
|
@Disabled
|
||||||
void noClassShouldThrowGenericException() {
|
void noClassShouldThrowGenericException() {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import pro.taskana.TaskState;
|
import pro.taskana.TaskState;
|
||||||
import pro.taskana.TaskSummary;
|
import pro.taskana.TaskSummary;
|
||||||
import pro.taskana.TaskanaEngine;
|
import pro.taskana.TaskanaEngine;
|
||||||
|
import pro.taskana.configuration.DB;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for TaskQueryImpl.
|
* Test for TaskQueryImpl.
|
||||||
|
|
@ -44,7 +45,7 @@ class TaskQueryImplTest {
|
||||||
when(taskanaEngine.getTaskService()).thenReturn(taskServiceMock);
|
when(taskanaEngine.getTaskService()).thenReturn(taskServiceMock);
|
||||||
|
|
||||||
Configuration configuration = new org.apache.ibatis.session.Configuration();
|
Configuration configuration = new org.apache.ibatis.session.Configuration();
|
||||||
configuration.setDatabaseId("h2");
|
configuration.setDatabaseId(DB.H2.dbProductId);
|
||||||
when(internalTaskanaEngine.getSqlSession()).thenReturn(sqlSession);
|
when(internalTaskanaEngine.getSqlSession()).thenReturn(sqlSession);
|
||||||
when(sqlSession.getConfiguration()).thenReturn(configuration);
|
when(sqlSession.getConfiguration()).thenReturn(configuration);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import pro.taskana.TaskanaSpringBootTest;
|
import pro.taskana.TaskanaSpringBootTest;
|
||||||
|
import pro.taskana.configuration.DB;
|
||||||
import pro.taskana.configuration.SpringTaskanaEngineConfiguration;
|
import pro.taskana.configuration.SpringTaskanaEngineConfiguration;
|
||||||
import pro.taskana.exceptions.SystemException;
|
import pro.taskana.exceptions.SystemException;
|
||||||
import pro.taskana.sampledata.SampleDataGenerator;
|
import pro.taskana.sampledata.SampleDataGenerator;
|
||||||
|
|
@ -32,7 +33,7 @@ class TestSchemaNameCustomizable {
|
||||||
void resetDb() {
|
void resetDb() {
|
||||||
SampleDataGenerator sampleDataGenerator;
|
SampleDataGenerator sampleDataGenerator;
|
||||||
try {
|
try {
|
||||||
if ("PostgreSQL".equals(dataSource.getConnection().getMetaData().getDatabaseProductName())) {
|
if (DB.POSTGRESS.dbProductname.equals(dataSource.getConnection().getMetaData().getDatabaseProductName())) {
|
||||||
isPostgres = true;
|
isPostgres = true;
|
||||||
schemaName = schemaName.toLowerCase();
|
schemaName = schemaName.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue