提交 f8109839 编写于 作者: T Tijs Rademakers

Merge branch 'master' of https://github.com/Activiti/Activiti

......@@ -116,14 +116,14 @@ public class GroupQueryImpl extends AbstractQuery<GroupQuery, Group> implements
public long executeCount(CommandContext commandContext) {
checkQueryOk();
return commandContext
.getGroupEntityManager()
.getGroupIdentityManager()
.findGroupCountByQueryCriteria(this);
}
public List<Group> executeList(CommandContext commandContext, Page page) {
checkQueryOk();
return commandContext
.getGroupEntityManager()
.getGroupIdentityManager()
.findGroupByQueryCriteria(this, page);
}
......
......@@ -25,13 +25,13 @@ public class NativeGroupQueryImpl extends AbstractNativeQuery<NativeGroupQuery,
public List<Group> executeList(CommandContext commandContext, Map<String, Object> parameterMap, int firstResult, int maxResults) {
return commandContext
.getGroupEntityManager()
.getGroupIdentityManager()
.findGroupsByNativeQuery(parameterMap, firstResult, maxResults);
}
public long executeCount(CommandContext commandContext, Map<String, Object> parameterMap) {
return commandContext
.getGroupEntityManager()
.getGroupIdentityManager()
.findGroupCountByNativeQuery(parameterMap);
}
......
......@@ -25,13 +25,13 @@ public class NativeUserQueryImpl extends AbstractNativeQuery<NativeUserQuery, Us
public List<User> executeList(CommandContext commandContext, Map<String, Object> parameterMap, int firstResult, int maxResults) {
return commandContext
.getUserEntityManager()
.getUserIdentityManager()
.findUsersByNativeQuery(parameterMap, firstResult, maxResults);
}
public long executeCount(CommandContext commandContext, Map<String, Object> parameterMap) {
return commandContext
.getUserEntityManager()
.getUserIdentityManager()
.findUserCountByNativeQuery(parameterMap);
}
......
......@@ -209,7 +209,7 @@ public class ProcessDefinitionQueryImpl extends AbstractQuery<ProcessDefinitionQ
if(authorizationUserId != null) {
List<Group> groups = Context
.getCommandContext()
.getGroupEntityManager()
.getGroupIdentityManager()
.findGroupsByUser(authorizationUserId);
List<String> groupIds = new ArrayList<String>();
for (Group group : groups) {
......
......@@ -401,7 +401,7 @@ public class TaskQueryImpl extends AbstractQuery<TaskQuery, Task> implements Tas
// and explain alternatives
List<Group> groups = Context
.getCommandContext()
.getGroupEntityManager()
.getGroupIdentityManager()
.findGroupsByUser(candidateUser);
List<String> groupIds = new ArrayList<String>();
for (Group group : groups) {
......
......@@ -145,14 +145,14 @@ public class UserQueryImpl extends AbstractQuery<UserQuery, User> implements Use
public long executeCount(CommandContext commandContext) {
checkQueryOk();
return commandContext
.getUserEntityManager()
.getUserIdentityManager()
.findUserCountByQueryCriteria(this);
}
public List<User> executeList(CommandContext commandContext, Page page) {
checkQueryOk();
return commandContext
.getUserEntityManager()
.getUserIdentityManager()
.findUserByQueryCriteria(this, page);
}
......
......@@ -136,6 +136,9 @@ import org.activiti.engine.impl.jobexecutor.TimerExecuteNestedActivityJobHandler
import org.activiti.engine.impl.jobexecutor.TimerStartEventJobHandler;
import org.activiti.engine.impl.jobexecutor.TimerSuspendProcessDefinitionHandler;
import org.activiti.engine.impl.persistence.GenericManagerFactory;
import org.activiti.engine.impl.persistence.GroupEntityManagerFactory;
import org.activiti.engine.impl.persistence.MembershipEntityManagerFactory;
import org.activiti.engine.impl.persistence.UserEntityManagerFactory;
import org.activiti.engine.impl.persistence.deploy.DefaultDeploymentCache;
import org.activiti.engine.impl.persistence.deploy.Deployer;
import org.activiti.engine.impl.persistence.deploy.DeploymentCache;
......@@ -146,7 +149,6 @@ import org.activiti.engine.impl.persistence.entity.CommentEntityManager;
import org.activiti.engine.impl.persistence.entity.DeploymentEntityManager;
import org.activiti.engine.impl.persistence.entity.EventSubscriptionEntityManager;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityManager;
import org.activiti.engine.impl.persistence.entity.GroupEntityManager;
import org.activiti.engine.impl.persistence.entity.HistoricActivityInstanceEntityManager;
import org.activiti.engine.impl.persistence.entity.HistoricDetailEntityManager;
import org.activiti.engine.impl.persistence.entity.HistoricIdentityLinkEntityManager;
......@@ -164,7 +166,6 @@ import org.activiti.engine.impl.persistence.entity.PropertyEntityManager;
import org.activiti.engine.impl.persistence.entity.ResourceEntityManager;
import org.activiti.engine.impl.persistence.entity.TableDataManager;
import org.activiti.engine.impl.persistence.entity.TaskEntityManager;
import org.activiti.engine.impl.persistence.entity.UserEntityManager;
import org.activiti.engine.impl.persistence.entity.VariableInstanceEntityManager;
import org.activiti.engine.impl.scripting.BeansResolverFactory;
import org.activiti.engine.impl.scripting.ResolverFactory;
......@@ -208,6 +209,7 @@ import org.slf4j.LoggerFactory;
/**
* @author Tom Baeyens
* @author Joram Barrez
*/
public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfiguration {
......@@ -257,6 +259,10 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
protected DbSqlSessionFactory dbSqlSessionFactory;
protected Map<Class<?>, SessionFactory> sessionFactories;
// Configurators ////////////////////////////////////////////////////////////
protected List<ProcessEngineConfigurator> configurators;
// DEPLOYERS ////////////////////////////////////////////////////////////////
protected BpmnDeployer bpmnDeployer;
......@@ -402,6 +408,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
initDelegateInterceptor();
initEventHandlers();
initFailedJobCommandFactory();
initConfigurators();
}
// failedJobCommandFactory ////////////////////////////////////////////////////////
......@@ -693,19 +700,21 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
addSessionFactory(new GenericManagerFactory(IdentityInfoEntityManager.class));
addSessionFactory(new GenericManagerFactory(IdentityLinkEntityManager.class));
addSessionFactory(new GenericManagerFactory(JobEntityManager.class));
addSessionFactory(new GenericManagerFactory(GroupEntityManager.class));
addSessionFactory(new GenericManagerFactory(MembershipEntityManager.class));
addSessionFactory(new GenericManagerFactory(ProcessDefinitionEntityManager.class));
addSessionFactory(new GenericManagerFactory(PropertyEntityManager.class));
addSessionFactory(new GenericManagerFactory(ResourceEntityManager.class));
addSessionFactory(new GenericManagerFactory(ByteArrayEntityManager.class));
addSessionFactory(new GenericManagerFactory(TableDataManager.class));
addSessionFactory(new GenericManagerFactory(TaskEntityManager.class));
addSessionFactory(new GenericManagerFactory(UserEntityManager.class));
addSessionFactory(new GenericManagerFactory(VariableInstanceEntityManager.class));
addSessionFactory(new GenericManagerFactory(EventSubscriptionEntityManager.class));
addSessionFactory(new GenericManagerFactory(HistoryManager.class));
addSessionFactory(new UserEntityManagerFactory());
addSessionFactory(new GroupEntityManagerFactory());
addSessionFactory(new MembershipEntityManagerFactory());
}
if (customSessionFactories!=null) {
for (SessionFactory sessionFactory: customSessionFactories) {
addSessionFactory(sessionFactory);
......@@ -717,6 +726,14 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
sessionFactories.put(sessionFactory.getSessionType(), sessionFactory);
}
protected void initConfigurators() {
if (configurators != null) {
for (ProcessEngineConfigurator configurator : configurators) {
configurator.configure(this);
}
}
}
// deployers ////////////////////////////////////////////////////////////////
protected void initDeployers() {
......@@ -1294,6 +1311,14 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
return this;
}
public List<ProcessEngineConfigurator> getConfigurators() {
return configurators;
}
public void setConfigurators(List<ProcessEngineConfigurator> configurators) {
this.configurators = configurators;
}
public BpmnDeployer getBpmnDeployer() {
return bpmnDeployer;
}
......
/* 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.cfg;
/**
* @author Joram Barrez
*/
public interface ProcessEngineConfigurator {
void configure(ProcessEngineConfigurationImpl processEngineConfiguration);
}
......@@ -34,7 +34,7 @@ public class CheckPassword implements Command<Boolean>, Serializable {
}
public Boolean execute(CommandContext commandContext) {
return commandContext.getUserEntityManager().checkPassword(userId, password);
return commandContext.getUserIdentityManager().checkPassword(userId, password);
}
}
......@@ -39,7 +39,7 @@ public class CreateGroupCmd implements Command<Group>, Serializable {
public Group execute(CommandContext commandContext) {
return commandContext
.getGroupEntityManager()
.getGroupIdentityManager()
.createNewGroup(groupId);
}
......
......@@ -29,7 +29,7 @@ public class CreateGroupQueryCmd implements Command<GroupQuery>, Serializable {
public GroupQuery execute(CommandContext commandContext) {
return commandContext
.getGroupEntityManager()
.getGroupIdentityManager()
.createNewGroupQuery();
}
......
......@@ -42,7 +42,7 @@ public class CreateMembershipCmd implements Command<Object>, Serializable {
throw new ActivitiIllegalArgumentException("groupId is null");
}
commandContext
.getMembershipEntityManager()
.getMembershipIdentityManager()
.createMembership(userId, groupId);
return null;
}
......
......@@ -39,7 +39,7 @@ public class CreateUserCmd implements Command<User>, Serializable {
public User execute(CommandContext commandContext) {
return commandContext
.getUserEntityManager()
.getUserIdentityManager()
.createNewUser(userId);
}
}
......@@ -29,7 +29,7 @@ public class CreateUserQueryCmd implements Command<UserQuery>, Serializable {
public UserQuery execute(CommandContext commandContext) {
return commandContext
.getUserEntityManager()
.getUserIdentityManager()
.createNewUserQuery();
}
......
......@@ -36,7 +36,7 @@ public class DeleteGroupCmd implements Command<Void>, Serializable {
throw new ActivitiIllegalArgumentException("groupId is null");
}
commandContext
.getGroupEntityManager()
.getGroupIdentityManager()
.deleteGroup(groupId);
return null;
......
......@@ -42,7 +42,7 @@ public class DeleteMembershipCmd implements Command<Void>, Serializable {
}
commandContext
.getMembershipEntityManager()
.getMembershipIdentityManager()
.deleteMembership(userId, groupId);
return null;
......
......@@ -36,7 +36,7 @@ public class DeleteUserCmd implements Command<Void>, Serializable {
throw new ActivitiIllegalArgumentException("userId is null");
}
commandContext
.getUserEntityManager()
.getUserIdentityManager()
.deleteUser(userId);
return null;
......
......@@ -41,7 +41,7 @@ public class GetUserPictureCmd implements Command<Picture>, Serializable {
throw new ActivitiIllegalArgumentException("userId is null");
}
UserEntity user = (UserEntity) commandContext
.getUserEntityManager()
.getUserIdentityManager()
.findUserById(userId);
if(user == null) {
throw new ActivitiObjectNotFoundException("user "+userId+" doesn't exist", User.class);
......
......@@ -38,11 +38,11 @@ public class SaveGroupCmd implements Command<Void>, Serializable {
}
if (group.getRevision()==0) {
commandContext
.getGroupEntityManager()
.getGroupIdentityManager()
.insertGroup(group);
} else {
commandContext
.getGroupEntityManager()
.getGroupIdentityManager()
.updateGroup(group);
}
......
......@@ -39,11 +39,11 @@ public class SaveUserCmd implements Command<Void>, Serializable {
}
if (user.getRevision()==0) {
commandContext
.getUserEntityManager()
.getUserIdentityManager()
.insertUser(user);
} else {
commandContext
.getUserEntityManager()
.getUserIdentityManager()
.updateUser(user);
}
......
......@@ -44,7 +44,7 @@ public class SetUserPictureCmd implements Command<Object>, Serializable {
throw new ActivitiIllegalArgumentException("userId is null");
}
UserEntity user = (UserEntity) commandContext
.getUserEntityManager()
.getUserIdentityManager()
.findUserById(userId);
if(user == null) {
throw new ActivitiObjectNotFoundException("user "+userId+" doesn't exist", User.class);
......
......@@ -32,7 +32,7 @@ import org.activiti.engine.impl.persistence.entity.CommentEntityManager;
import org.activiti.engine.impl.persistence.entity.DeploymentEntityManager;
import org.activiti.engine.impl.persistence.entity.EventSubscriptionEntityManager;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityManager;
import org.activiti.engine.impl.persistence.entity.GroupEntityManager;
import org.activiti.engine.impl.persistence.entity.GroupIdentityManager;
import org.activiti.engine.impl.persistence.entity.HistoricActivityInstanceEntityManager;
import org.activiti.engine.impl.persistence.entity.HistoricDetailEntityManager;
import org.activiti.engine.impl.persistence.entity.HistoricIdentityLinkEntityManager;
......@@ -42,14 +42,14 @@ import org.activiti.engine.impl.persistence.entity.HistoricVariableInstanceEntit
import org.activiti.engine.impl.persistence.entity.IdentityInfoEntityManager;
import org.activiti.engine.impl.persistence.entity.IdentityLinkEntityManager;
import org.activiti.engine.impl.persistence.entity.JobEntityManager;
import org.activiti.engine.impl.persistence.entity.MembershipEntityManager;
import org.activiti.engine.impl.persistence.entity.MembershipIdentityManager;
import org.activiti.engine.impl.persistence.entity.ModelEntityManager;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityManager;
import org.activiti.engine.impl.persistence.entity.PropertyEntityManager;
import org.activiti.engine.impl.persistence.entity.ResourceEntityManager;
import org.activiti.engine.impl.persistence.entity.TableDataManager;
import org.activiti.engine.impl.persistence.entity.TaskEntityManager;
import org.activiti.engine.impl.persistence.entity.UserEntityManager;
import org.activiti.engine.impl.persistence.entity.UserIdentityManager;
import org.activiti.engine.impl.persistence.entity.VariableInstanceEntityManager;
import org.activiti.engine.impl.pvm.runtime.AtomicOperation;
import org.activiti.engine.impl.pvm.runtime.InterpretableExecution;
......@@ -271,20 +271,20 @@ public class CommandContext {
return getSession(JobEntityManager.class);
}
public UserEntityManager getUserEntityManager() {
return getSession(UserEntityManager.class);
public UserIdentityManager getUserIdentityManager() {
return getSession(UserIdentityManager.class);
}
public GroupEntityManager getGroupEntityManager() {
return getSession(GroupEntityManager.class);
public GroupIdentityManager getGroupIdentityManager() {
return getSession(GroupIdentityManager.class);
}
public IdentityInfoEntityManager getIdentityInfoEntityManager() {
return getSession(IdentityInfoEntityManager.class);
}
public MembershipEntityManager getMembershipEntityManager() {
return getSession(MembershipEntityManager.class);
public MembershipIdentityManager getMembershipIdentityManager() {
return getSession(MembershipIdentityManager.class);
}
public AttachmentEntityManager getAttachmentEntityManager() {
......
......@@ -22,21 +22,21 @@ import org.activiti.engine.impl.persistence.entity.AttachmentEntityManager;
import org.activiti.engine.impl.persistence.entity.ByteArrayEntityManager;
import org.activiti.engine.impl.persistence.entity.DeploymentEntityManager;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityManager;
import org.activiti.engine.impl.persistence.entity.GroupEntityManager;
import org.activiti.engine.impl.persistence.entity.GroupIdentityManager;
import org.activiti.engine.impl.persistence.entity.HistoricActivityInstanceEntityManager;
import org.activiti.engine.impl.persistence.entity.HistoricDetailEntityManager;
import org.activiti.engine.impl.persistence.entity.HistoricIdentityLinkEntityManager;
import org.activiti.engine.impl.persistence.entity.HistoricProcessInstanceEntityManager;
import org.activiti.engine.impl.persistence.entity.HistoricVariableInstanceEntityManager;
import org.activiti.engine.impl.persistence.entity.HistoricTaskInstanceEntityManager;
import org.activiti.engine.impl.persistence.entity.HistoricVariableInstanceEntityManager;
import org.activiti.engine.impl.persistence.entity.IdentityInfoEntityManager;
import org.activiti.engine.impl.persistence.entity.IdentityLinkEntityManager;
import org.activiti.engine.impl.persistence.entity.MembershipEntityManager;
import org.activiti.engine.impl.persistence.entity.MembershipIdentityManager;
import org.activiti.engine.impl.persistence.entity.ModelEntityManager;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityManager;
import org.activiti.engine.impl.persistence.entity.ResourceEntityManager;
import org.activiti.engine.impl.persistence.entity.TaskEntityManager;
import org.activiti.engine.impl.persistence.entity.UserEntityManager;
import org.activiti.engine.impl.persistence.entity.UserIdentityManager;
import org.activiti.engine.impl.persistence.entity.VariableInstanceEntityManager;
......@@ -122,20 +122,20 @@ public abstract class AbstractManager implements Session {
return getSession(HistoricIdentityLinkEntityManager.class);
}
protected UserEntityManager getUserManager() {
return getSession(UserEntityManager.class);
protected UserIdentityManager getUserIdentityManager() {
return getSession(UserIdentityManager.class);
}
protected GroupEntityManager getGroupManager() {
return getSession(GroupEntityManager.class);
protected GroupIdentityManager getGroupIdentityManager() {
return getSession(GroupIdentityManager.class);
}
protected IdentityInfoEntityManager getIdentityInfoManager() {
return getSession(IdentityInfoEntityManager.class);
}
protected MembershipEntityManager getMembershipManager() {
return getSession(MembershipEntityManager.class);
protected MembershipIdentityManager getMembershipIdentityManager() {
return getSession(MembershipIdentityManager.class);
}
protected AttachmentEntityManager getAttachmentManager() {
......
/* 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.persistence;
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.GroupEntityManager;
import org.activiti.engine.impl.persistence.entity.GroupIdentityManager;
/**
* @author Joram Barrez
*/
public class GroupEntityManagerFactory implements SessionFactory {
public Class< ? > getSessionType() {
return GroupIdentityManager.class;
}
public Session openSession() {
return new GroupEntityManager();
}
}
/* 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.persistence;
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.MembershipEntityManager;
import org.activiti.engine.impl.persistence.entity.MembershipIdentityManager;
/**
* @author Joram Barrez
*/
public class MembershipEntityManagerFactory implements SessionFactory {
public Class< ? > getSessionType() {
return MembershipIdentityManager.class;
}
public Session openSession() {
return new MembershipEntityManager();
}
}
/* 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.persistence;
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.UserEntityManager;
import org.activiti.engine.impl.persistence.entity.UserIdentityManager;
/**
* @author Joram Barrez
*/
public class UserEntityManagerFactory implements SessionFactory {
public Class< ? > getSessionType() {
return UserIdentityManager.class;
}
public Session openSession() {
return new UserEntityManager();
}
}
......@@ -33,7 +33,7 @@ import java.util.Map;
* @author Saeid Mirzaei
* @author Joram Barrez
*/
public class GroupEntityManager extends AbstractManager {
public class GroupEntityManager extends AbstractManager implements GroupIdentityManager {
public Group createNewGroup(String groupId) {
return new GroupEntity(groupId);
......@@ -68,22 +68,11 @@ public class GroupEntityManager extends AbstractManager {
return (Long) getDbSqlSession().selectOne("selectGroupCountByQueryCriteria", query);
}
public GroupEntity findGroupById(String groupId) {
return (GroupEntity) getDbSqlSession().selectOne("selectGroupById", groupId);
}
@SuppressWarnings("unchecked")
public List<Group> findGroupsByUser(String userId) {
return getDbSqlSession().selectList("selectGroupsByUserId", userId);
}
@SuppressWarnings("unchecked")
public List<Group> findPotentialStarterUsers(String proceDefId) {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("procDefId", proceDefId);
return (List<Group>) getDbSqlSession().selectOne("selectGroupByQueryCriteria", parameters);
}
@SuppressWarnings("unchecked")
public List<Group> findGroupsByNativeQuery(Map<String, Object> parameterMap, int firstResult, int maxResults) {
return getDbSqlSession().selectListWithRawParameter("selectGroupByNativeQuery", parameterMap, firstResult, maxResults);
......
/* 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.persistence.entity;
import java.util.List;
import java.util.Map;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.GroupQuery;
import org.activiti.engine.impl.GroupQueryImpl;
import org.activiti.engine.impl.Page;
/**
* @author Joram Barrez
*/
public interface GroupIdentityManager {
Group createNewGroup(String groupId);
void insertGroup(Group group);
void updateGroup(GroupEntity updatedGroup);
void deleteGroup(String groupId);
GroupQuery createNewGroupQuery();
List<Group> findGroupByQueryCriteria(GroupQueryImpl query, Page page);
long findGroupCountByQueryCriteria(GroupQueryImpl query);
List<Group> findGroupsByUser(String userId);
List<Group> findGroupsByNativeQuery(Map<String, Object> parameterMap, int firstResult, int maxResults);
long findGroupCountByNativeQuery(Map<String, Object> parameterMap);
}
......@@ -22,7 +22,7 @@ import org.activiti.engine.impl.persistence.AbstractManager;
/**
* @author Tom Baeyens
*/
public class MembershipEntityManager extends AbstractManager {
public class MembershipEntityManager extends AbstractManager implements MembershipIdentityManager {
public void createMembership(String userId, String groupId) {
MembershipEntity membershipEntity = new MembershipEntity();
......
/* 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.persistence.entity;
/**
* @author Joram Barrez
*/
public interface MembershipIdentityManager {
void createMembership(String userId, String groupId);
void deleteMembership(String userId, String groupId);
}
......@@ -34,7 +34,7 @@ import java.util.Map;
* @author Saeid Mirzaei
* @author Joram Barrez
*/
public class UserEntityManager extends AbstractManager {
public class UserEntityManager extends AbstractManager implements UserIdentityManager {
public User createNewUser(String userId) {
return new UserEntity(userId);
......
/* 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.persistence.entity;
import java.util.List;
import java.util.Map;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.identity.UserQuery;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.UserQueryImpl;
/**
* @author Joram Barrez
*/
public interface UserIdentityManager {
User createNewUser(String userId);
void insertUser(User user);
void updateUser(UserEntity updatedUser);
UserEntity findUserById(String userId);
void deleteUser(String userId);
List<User> findUserByQueryCriteria(UserQueryImpl query, Page page);
long findUserCountByQueryCriteria(UserQueryImpl query);
List<Group> findGroupsByUser(String userId);
UserQuery createNewUserQuery();
IdentityInfoEntity findUserInfoByUserIdAndKey(String userId, String key);
List<String> findUserInfoKeysByUserIdAndType(String userId, String type);
Boolean checkPassword(String userId, String password);
List<User> findPotentialStarterUsers(String proceDefId);
List<User> findUsersByNativeQuery(Map<String, Object> parameterMap, int firstResult, int maxResults);
long findUserCountByNativeQuery(Map<String, Object> parameterMap);
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<name>Activiti - LDAP</name>
<artifactId>activiti-ldap</artifactId>
<parent>
<groupId>org.activiti</groupId>
<artifactId>activiti-root</artifactId>
<relativePath>../..</relativePath>
<version>5.13-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Apache DS (LDAP Server) -->
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-core</artifactId>
<version>1.5.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-protocol-ldap</artifactId>
<version>1.5.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.shared</groupId>
<artifactId>shared-ldap</artifactId>
<version>0.9.17</version>
<scope>test</scope>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
<!-- Testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<!-- LDAP testing support -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.1.4.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.1.4.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<version>1.3.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core-tiger</artifactId>
<version>1.3.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>3.1.4.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>distro</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
/* 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.ldap;
import javax.naming.directory.InitialDirContext;
/**
* @author Joram Barrez
*/
public interface LDAPCallBack<T> {
T executeInContext(InitialDirContext initialDirContext);
}
/* 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.ldap;
import java.util.HashMap;
import java.util.Map;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurator;
/**
* @author Joram Barrez
*/
public class LDAPConfigurator implements ProcessEngineConfigurator {
// Server connection params
protected String server;
protected int port;
protected String user;
protected String password;
protected String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
protected String securityAuthentication = "simple";
// For parameters like connection pooling settings, etc.
protected Map<String, String> customConnectionParameters = new HashMap<String, String>();
// Query configuration
protected String baseDn;
protected int searchTimeLimit = 0; // Default '0' == wait forever
protected String queryUserByUserId;
protected String queryGroupsForUser;
// Attribute names
protected String userIdAttribute;
protected String userFirstNameAttribute;
protected String userLastNameAttribute;
protected String groupIdAttribute;
protected String groupNameAttribute;
protected String groupTypeAttribute;
// Pluggable factories
protected LDAPUserManagerFactory ldapUserManagerFactory;
protected LDAPGroupManagerFactory ldapGroupManagerFactory;
protected LDAPMembershipManagerFactory ldapMembershipManagerFactory;
// Pluggable query helper bean
protected LDAPQueryBuilder ldapQueryBuilder = new LDAPQueryBuilder();
// Group caching
protected int groupCacheSize = -1;
protected long groupCacheExpirationTime = 3600000L; // default: one hour
public void configure(ProcessEngineConfigurationImpl processEngineConfiguration) {
LDAPUserManagerFactory ldapUserManagerFactory = getLdapUserManagerFactory();
processEngineConfiguration.getSessionFactories().put(ldapUserManagerFactory.getSessionType(), ldapUserManagerFactory);
LDAPGroupManagerFactory ldapGroupManagerFactory = getLdapGroupManagerFactory();
processEngineConfiguration.getSessionFactories().put(ldapGroupManagerFactory.getSessionType(), ldapGroupManagerFactory);
}
// Can be overwritten for custom factories
protected LDAPUserManagerFactory getLdapUserManagerFactory() {
if (this.ldapUserManagerFactory != null) {
this.ldapUserManagerFactory.setLdapConfigurator(this);
return this.ldapUserManagerFactory;
}
return new LDAPUserManagerFactory(this);
}
protected LDAPGroupManagerFactory getLdapGroupManagerFactory() {
if (this.ldapGroupManagerFactory != null) {
this.ldapGroupManagerFactory.setLdapConfigurator(this);
return this.ldapGroupManagerFactory;
}
return new LDAPGroupManagerFactory(this);
}
protected LDAPMembershipManagerFactory getLdapMembershipManagerFactory() {
if (this.ldapMembershipManagerFactory != null) {
this.ldapMembershipManagerFactory.setLdapConfigurator(this);
}
return new LDAPMembershipManagerFactory(this);
}
// Getters and Setters
public String getServer() {
return server;
}
public void setServer(String server) {
this.server = server;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getInitialContextFactory() {
return initialContextFactory;
}
public void setInitialContextFactory(String initialContextFactory) {
this.initialContextFactory = initialContextFactory;
}
public String getSecurityAuthentication() {
return securityAuthentication;
}
public void setSecurityAuthentication(String securityAuthentication) {
this.securityAuthentication = securityAuthentication;
}
public Map<String, String> getCustomConnectionParameters() {
return customConnectionParameters;
}
public void setCustomConnectionParameters(Map<String, String> customConnectionParameters) {
this.customConnectionParameters = customConnectionParameters;
}
public String getBaseDn() {
return baseDn;
}
public void setBaseDn(String baseDn) {
this.baseDn = baseDn;
}
public int getSearchTimeLimit() {
return searchTimeLimit;
}
public void setSearchTimeLimit(int searchTimeLimit) {
this.searchTimeLimit = searchTimeLimit;
}
public String getQueryUserByUserId() {
return queryUserByUserId;
}
public void setQueryUserByUserId(String queryUserByUserId) {
this.queryUserByUserId = queryUserByUserId;
}
public String getQueryGroupsForUser() {
return queryGroupsForUser;
}
public void setQueryGroupsForUser(String queryGroupsForUser) {
this.queryGroupsForUser = queryGroupsForUser;
}
public String getUserIdAttribute() {
return userIdAttribute;
}
public void setUserIdAttribute(String userIdAttribute) {
this.userIdAttribute = userIdAttribute;
}
public String getUserFirstNameAttribute() {
return userFirstNameAttribute;
}
public void setUserFirstNameAttribute(String userFirstNameAttribute) {
this.userFirstNameAttribute = userFirstNameAttribute;
}
public String getUserLastNameAttribute() {
return userLastNameAttribute;
}
public void setUserLastNameAttribute(String userLastNameAttribute) {
this.userLastNameAttribute = userLastNameAttribute;
}
public String getGroupIdAttribute() {
return groupIdAttribute;
}
public void setGroupIdAttribute(String groupIdAttribute) {
this.groupIdAttribute = groupIdAttribute;
}
public String getGroupNameAttribute() {
return groupNameAttribute;
}
public void setGroupNameAttribute(String groupNameAttribute) {
this.groupNameAttribute = groupNameAttribute;
}
public String getGroupTypeAttribute() {
return groupTypeAttribute;
}
public void setGroupTypeAttribute(String groupTypeAttribute) {
this.groupTypeAttribute = groupTypeAttribute;
}
public void setLdapUserManagerFactory(LDAPUserManagerFactory ldapUserManagerFactory) {
this.ldapUserManagerFactory = ldapUserManagerFactory;
}
public void setLdapGroupManagerFactory(LDAPGroupManagerFactory ldapGroupManagerFactory) {
this.ldapGroupManagerFactory = ldapGroupManagerFactory;
}
public void setLdapMembershipManagerFactory(LDAPMembershipManagerFactory ldapMembershipManagerFactory) {
this.ldapMembershipManagerFactory = ldapMembershipManagerFactory;
}
public LDAPQueryBuilder getLdapQueryBuilder() {
return ldapQueryBuilder;
}
public void setLdapQueryBuilder(LDAPQueryBuilder ldapQueryBuilder) {
this.ldapQueryBuilder = ldapQueryBuilder;
}
public int getGroupCacheSize() {
return groupCacheSize;
}
public void setGroupCacheSize(int groupCacheSize) {
this.groupCacheSize = groupCacheSize;
}
public long getGroupCacheExpirationTime() {
return groupCacheExpirationTime;
}
public void setGroupCacheExpirationTime(long groupCacheExpirationTime) {
this.groupCacheExpirationTime = groupCacheExpirationTime;
}
}
/* 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.ldap;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
import org.activiti.engine.ActivitiException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LDAPConnectionUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(LDAPConnectionUtil.class);
public static InitialDirContext creatDirectoryContext(LDAPConfigurator ldapConfigurator) {
return createDirectoryContext(ldapConfigurator, ldapConfigurator.getUser(), ldapConfigurator.getPassword());
}
public static InitialDirContext createDirectoryContext(LDAPConfigurator ldapConfigurator, String principal, String credentials) {
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, ldapConfigurator.getInitialContextFactory());
properties.put(Context.PROVIDER_URL, ldapConfigurator.getServer() + ":" + ldapConfigurator.getPort());
properties.put(Context.SECURITY_PRINCIPAL, principal);
properties.put(Context.SECURITY_CREDENTIALS, credentials);
if (ldapConfigurator.getCustomConnectionParameters() != null) {
for (String customParameter : ldapConfigurator.getCustomConnectionParameters().keySet()) {
properties.put(customParameter, ldapConfigurator.getCustomConnectionParameters().get(customParameter));
}
}
InitialDirContext context;
try {
context = new InitialDirContext(properties);
} catch (NamingException e) {
throw new ActivitiException("Could not create InitialDirContext for LDAP connection : " + e.getMessage(), e);
}
return context;
}
public static void closeDirectoryContext(InitialDirContext initialDirContext) {
try {
initialDirContext.close();
} catch (NamingException e) {
LOGGER.warn("Could not close InitialDirContext correctly!", e);
}
}
}
/* 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.ldap;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.identity.Group;
import org.activiti.engine.impl.util.ClockUtil;
/**
* @author Joram Barrez
*/
public class LDAPGroupCache {
protected Map<String, LDAPGroupCacheEntry> groupCache;
protected long expirationTime;
protected LDAPGroupCacheListener ldapCacheListener;
public LDAPGroupCache(final int cacheSize, final long expirationTime) {
// From http://stackoverflow.com/questions/224868/easy-simple-to-use-lru-cache-in-java
this.groupCache =new LinkedHashMap<String, LDAPGroupCache.LDAPGroupCacheEntry>(cacheSize + 1, 0.75f, true) {
private static final long serialVersionUID = 5207574193173514579L;
protected boolean removeEldestEntry(java.util.Map.Entry<String, LDAPGroupCacheEntry> eldest) {
boolean removeEldest = size() > cacheSize;
if (removeEldest && ldapCacheListener != null) {
ldapCacheListener.cacheEviction(eldest.getKey());
}
return removeEldest;
}
};
this.expirationTime = expirationTime;
}
public void add(String userId, List<Group> groups) {
this.groupCache.put(userId, new LDAPGroupCacheEntry(ClockUtil.getCurrentTime(), groups));
}
public List<Group> get(String userId) {
LDAPGroupCacheEntry cacheEntry = groupCache.get(userId);
if (cacheEntry != null) {
if ((ClockUtil.getCurrentTime().getTime() - cacheEntry.getTimestamp().getTime()) < expirationTime) {
if (ldapCacheListener != null) {
ldapCacheListener.cacheHit(userId);
}
return cacheEntry.getGroups();
} else {
this.groupCache.remove(userId);
if (ldapCacheListener != null) {
ldapCacheListener.cacheExpired(userId);
ldapCacheListener.cacheEviction(userId);
}
}
}
if (ldapCacheListener != null) {
ldapCacheListener.cacheMiss(userId);
}
return null;
}
public void clear() {
groupCache.clear();
}
public Map<String, LDAPGroupCacheEntry> getGroupCache() {
return groupCache;
}
public void setGroupCache(Map<String, LDAPGroupCacheEntry> groupCache) {
this.groupCache = groupCache;
}
public long getExpirationTime() {
return expirationTime;
}
public void setExpirationTime(long expirationTime) {
this.expirationTime = expirationTime;
}
public LDAPGroupCacheListener getLdapCacheListener() {
return ldapCacheListener;
}
public void setLdapCacheListener(LDAPGroupCacheListener ldapCacheListener) {
this.ldapCacheListener = ldapCacheListener;
}
// Helper classes ////////////////////////////////////
static class LDAPGroupCacheEntry {
protected Date timestamp;
protected List<Group> groups;
public LDAPGroupCacheEntry() {
}
public LDAPGroupCacheEntry(Date timestamp, List<Group> groups) {
this.timestamp = timestamp;
this.groups = groups;
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public List<Group> getGroups() {
return groups;
}
public void setGroups(List<Group> groups) {
this.groups = groups;
}
}
// Cache listeners. Currently not yet exposed (only programmatically for the moment)
// Experimental stuff!
public static interface LDAPGroupCacheListener {
void cacheHit(String userId);
void cacheMiss(String userId);
void cacheEviction(String userId);
void cacheExpired(String userId);
}
}
/* 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.ldap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.GroupQuery;
import org.activiti.engine.impl.GroupQueryImpl;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.persistence.AbstractManager;
import org.activiti.engine.impl.persistence.entity.GroupEntity;
import org.activiti.engine.impl.persistence.entity.GroupIdentityManager;
/**
* @author Joram Barrez
*/
public class LDAPGroupManager extends AbstractManager implements GroupIdentityManager {
protected LDAPConfigurator ldapConfigurator;
protected LDAPGroupCache ldapGroupCache;
public LDAPGroupManager(LDAPConfigurator ldapConfigurator) {
this.ldapConfigurator = ldapConfigurator;
}
public LDAPGroupManager(LDAPConfigurator ldapConfigurator, LDAPGroupCache ldapGroupCache) {
this.ldapConfigurator = ldapConfigurator;
this.ldapGroupCache = ldapGroupCache;
}
@Override
public Group createNewGroup(String groupId) {
throw new ActivitiException("LDAP group manager doesn't support creating a new group");
}
@Override
public void insertGroup(Group group) {
throw new ActivitiException("LDAP group manager doesn't support inserting a group");
}
@Override
public void updateGroup(GroupEntity updatedGroup) {
throw new ActivitiException("LDAP group manager doesn't support updating a group");
}
@Override
public void deleteGroup(String groupId) {
throw new ActivitiException("LDAP group manager doesn't support deleting a group");
}
@Override
public GroupQuery createNewGroupQuery() {
throw new ActivitiException("LDAP group manager doesn't support querying");
}
@Override
public List<Group> findGroupByQueryCriteria(GroupQueryImpl query, Page page) {
throw new ActivitiException("LDAP group manager doesn't support querying");
}
@Override
public long findGroupCountByQueryCriteria(GroupQueryImpl query) {
throw new ActivitiException("LDAP group manager doesn't support querying");
}
@Override
public List<Group> findGroupsByUser(final String userId) {
// First try the cache (if one is defined)
if (ldapGroupCache != null) {
List<Group> groups = ldapGroupCache.get(userId);
if (groups != null) {
return groups;
}
}
// Do the search against Ldap
LDAPTemplate ldapTemplate = new LDAPTemplate(ldapConfigurator);
return ldapTemplate.execute(new LDAPCallBack<List<Group>>() {
public List<Group> executeInContext(InitialDirContext initialDirContext) {
String searchExpression = ldapConfigurator.getLdapQueryBuilder().buildQueryGroupsForUser(ldapConfigurator, userId);
List<Group> groups = new ArrayList<Group>();
try {
NamingEnumeration< ? > namingEnum = initialDirContext.search(ldapConfigurator.getBaseDn(), searchExpression, createSearchControls());
while (namingEnum.hasMore()) { // Should be only one
SearchResult result = (SearchResult) namingEnum.next();
GroupEntity group = new GroupEntity();
if (ldapConfigurator.getGroupIdAttribute() != null) {
group.setId(result.getAttributes().get(ldapConfigurator.getGroupIdAttribute()).get().toString());
}
if (ldapConfigurator.getGroupNameAttribute() != null) {
group.setName(result.getAttributes().get(ldapConfigurator.getGroupNameAttribute()).get().toString());
}
if (ldapConfigurator.getGroupTypeAttribute() != null) {
group.setType(result.getAttributes().get(ldapConfigurator.getGroupTypeAttribute()).get().toString());
}
groups.add(group);
}
namingEnum.close();
// Cache results for later
if (ldapGroupCache != null) {
ldapGroupCache.add(userId, groups);
}
return groups;
} catch (NamingException e) {
throw new ActivitiException("Could not find groups for user " + userId, e);
}
}
});
}
@Override
public List<Group> findGroupsByNativeQuery(Map<String, Object> parameterMap, int firstResult, int maxResults) {
throw new ActivitiException("LDAP group manager doesn't support querying");
}
@Override
public long findGroupCountByNativeQuery(Map<String, Object> parameterMap) {
throw new ActivitiException("LDAP group manager doesn't support querying");
}
protected SearchControls createSearchControls() {
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setTimeLimit(ldapConfigurator.getSearchTimeLimit());
return searchControls;
}
}
/* 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.ldap;
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.GroupIdentityManager;
import org.activiti.ldap.LDAPGroupCache.LDAPGroupCacheListener;
/**
* @author Joram Barrez
*/
public class LDAPGroupManagerFactory implements SessionFactory {
protected LDAPConfigurator ldapConfigurator;
protected LDAPGroupCache ldapGroupCache;
protected LDAPGroupCacheListener ldapCacheListener;
public LDAPGroupManagerFactory(LDAPConfigurator ldapConfigurator) {
this.ldapConfigurator = ldapConfigurator;
if (ldapConfigurator.getGroupCacheSize() > 0) {
ldapGroupCache = new LDAPGroupCache(ldapConfigurator.getGroupCacheSize(), ldapConfigurator.getGroupCacheExpirationTime());
if (ldapCacheListener != null) {
ldapGroupCache.setLdapCacheListener(ldapCacheListener);
}
}
}
@Override
public Class<?> getSessionType() {
return GroupIdentityManager.class;
}
@Override
public Session openSession() {
if (ldapGroupCache == null) {
return new LDAPGroupManager(ldapConfigurator);
} else {
return new LDAPGroupManager(ldapConfigurator, ldapGroupCache);
}
}
public LDAPConfigurator getLdapConfigurator() {
return ldapConfigurator;
}
public void setLdapConfigurator(LDAPConfigurator ldapConfigurator) {
this.ldapConfigurator = ldapConfigurator;
}
public LDAPGroupCache getLdapGroupCache() {
return ldapGroupCache;
}
public void setLdapGroupCache(LDAPGroupCache ldapGroupCache) {
this.ldapGroupCache = ldapGroupCache;
}
public LDAPGroupCacheListener getLdapCacheListener() {
return ldapCacheListener;
}
public void setLdapCacheListener(LDAPGroupCacheListener ldapCacheListener) {
this.ldapCacheListener = ldapCacheListener;
}
}
/* 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.ldap;
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.MembershipIdentityManager;
/**
* @author Joram Barrez
*/
public class LDAPMembershipManagerFactory implements SessionFactory {
protected LDAPConfigurator ldapConfigurator;
public LDAPMembershipManagerFactory(LDAPConfigurator ldapConfigurator) {
this.ldapConfigurator = ldapConfigurator;
}
@Override
public Class<?> getSessionType() {
return MembershipIdentityManager.class;
}
@Override
public Session openSession() {
throw new UnsupportedOperationException("Memberships are not supported in ldap");
}
public LDAPConfigurator getLdapConfigurator() {
return ldapConfigurator;
}
public void setLdapConfigurator(LDAPConfigurator ldapConfigurator) {
this.ldapConfigurator = ldapConfigurator;
}
}
/* 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.ldap;
import java.text.MessageFormat;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Joram Barrez
*/
public class LDAPQueryBuilder {
protected static final Logger LOGGER = LoggerFactory.getLogger(LDAPQueryBuilder.class);
public String buildQueryByUserId(LDAPConfigurator ldapConfigurator, String userId) {
String searchExpression = null;
if (ldapConfigurator.getQueryUserByUserId() != null) {
searchExpression = MessageFormat.format(ldapConfigurator.getQueryUserByUserId(), userId);
} else {
searchExpression = userId;
}
return searchExpression;
}
public String buildQueryGroupsForUser(final LDAPConfigurator ldapConfigurator, final String userId) {
String searchExpression = null;
if (ldapConfigurator.getQueryGroupsForUser() != null) {
// Fetch the dn of the user
LDAPTemplate ldapTemplate = new LDAPTemplate(ldapConfigurator);
String userDn = ldapTemplate.execute(new LDAPCallBack<String>() {
public String executeInContext(InitialDirContext initialDirContext) {
String userDnSearch = buildQueryByUserId(ldapConfigurator, userId);
try {
NamingEnumeration< ? > namingEnum = initialDirContext.search(ldapConfigurator.getBaseDn(), userDnSearch, createSearchControls(ldapConfigurator));
while (namingEnum.hasMore()) { // Should be only one
SearchResult result = (SearchResult) namingEnum.next();
return result.getNameInNamespace();
}
namingEnum.close();
} catch (NamingException e) {
LOGGER.debug("Could not find user dn : " + e.getMessage(), e);
}
return null;
}
});
searchExpression = MessageFormat.format(ldapConfigurator.getQueryGroupsForUser(), userDn);
} else {
searchExpression = userId;
}
return searchExpression;
}
protected SearchControls createSearchControls(LDAPConfigurator ldapConfigurator) {
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setTimeLimit(ldapConfigurator.getSearchTimeLimit());
return searchControls;
}
}
/* 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.ldap;
import javax.naming.directory.InitialDirContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Joram Barrez
*/
public class LDAPTemplate {
private static final Logger LOGGER = LoggerFactory.getLogger(LDAPTemplate.class);
protected LDAPConfigurator ldapConfigurator;
public LDAPTemplate(LDAPConfigurator ldapConfigurator) {
this.ldapConfigurator = ldapConfigurator;
}
public <T> T execute(LDAPCallBack<T> ldapCallBack) {
InitialDirContext initialDirContext = null;
try {
initialDirContext = LDAPConnectionUtil.creatDirectoryContext(ldapConfigurator);
} catch (Exception e) {
LOGGER.info("Could not create LDAP connection : " + e.getMessage(), e);
}
T result = ldapCallBack.executeInContext(initialDirContext);
LDAPConnectionUtil.closeDirectoryContext(initialDirContext);
return result;
}
public LDAPConfigurator getLdapConfigurator() {
return ldapConfigurator;
}
public void setLdapConfigurator(LDAPConfigurator ldapConfigurator) {
this.ldapConfigurator = ldapConfigurator;
}
}
/* 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.ldap;
import java.util.List;
import java.util.Map;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.identity.UserQuery;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.UserQueryImpl;
import org.activiti.engine.impl.persistence.AbstractManager;
import org.activiti.engine.impl.persistence.entity.IdentityInfoEntity;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.activiti.engine.impl.persistence.entity.UserIdentityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Joram Barrez
*/
public class LDAPUserManager extends AbstractManager implements UserIdentityManager {
private static Logger logger = LoggerFactory.getLogger(LDAPUserManager.class);
protected LDAPConfigurator ldapConfigurator;
public LDAPUserManager(LDAPConfigurator ldapConfigurator) {
this.ldapConfigurator = ldapConfigurator;
}
@Override
public User createNewUser(String userId) {
throw new ActivitiException("LDAP user manager doesn't support creating a new user");
}
@Override
public void insertUser(User user) {
throw new ActivitiException("LDAP user manager doesn't support inserting a new user");
}
@Override
public void updateUser(UserEntity updatedUser) {
throw new ActivitiException("LDAP user manager doesn't support updating a user");
}
@Override
public UserEntity findUserById(final String userId) {
LDAPTemplate ldapTemplate = new LDAPTemplate(ldapConfigurator);
return ldapTemplate.execute(new LDAPCallBack<UserEntity>() {
public UserEntity executeInContext(InitialDirContext initialDirContext) {
try {
String searchExpression = ldapConfigurator.getLdapQueryBuilder().buildQueryByUserId(ldapConfigurator, userId);
NamingEnumeration< ? > namingEnum = initialDirContext.search(ldapConfigurator.getBaseDn(), searchExpression, createSearchControls());
UserEntity user = new UserEntity();
while (namingEnum.hasMore()) { // Should be only one
SearchResult result = (SearchResult) namingEnum.next();
user.setId(userId);
if (ldapConfigurator.getUserFirstNameAttribute() != null) {
user.setFirstName(result.getAttributes().get(ldapConfigurator.getUserFirstNameAttribute()).get().toString());
}
if (ldapConfigurator.getUserLastNameAttribute() != null) {
user.setLastName(result.getAttributes().get(ldapConfigurator.getUserLastNameAttribute()).get().toString());
}
}
namingEnum.close();
return user;
} catch (NamingException ne) {
logger.debug("Could not find user " + userId + " : " + ne.getMessage(), ne);
return null;
}
}
});
}
@Override
public void deleteUser(String userId) {
throw new ActivitiException("LDAP user manager doesn't support deleting a user");
}
@Override
public List<User> findUserByQueryCriteria(UserQueryImpl query, Page page) {
throw new ActivitiException("LDAP user manager doesn't support querying");
}
@Override
public long findUserCountByQueryCriteria(UserQueryImpl query) {
throw new ActivitiException("LDAP user manager doesn't support querying");
}
@Override
public List<Group> findGroupsByUser(String userId) {
throw new ActivitiException("LDAP user manager doesn't support querying");
}
@Override
public UserQuery createNewUserQuery() {
throw new ActivitiException("LDAP user manager doesn't support querying");
}
@Override
public IdentityInfoEntity findUserInfoByUserIdAndKey(String userId, String key) {
throw new ActivitiException("LDAP user manager doesn't support querying");
}
@Override
public List<String> findUserInfoKeysByUserIdAndType(String userId, String type) {
throw new ActivitiException("LDAP user manager doesn't support querying");
}
@Override
public List<User> findPotentialStarterUsers(String proceDefId) {
throw new ActivitiException("LDAP user manager doesn't support querying");
}
@Override
public List<User> findUsersByNativeQuery(Map<String, Object> parameterMap, int firstResult, int maxResults) {
throw new ActivitiException("LDAP user manager doesn't support querying");
}
@Override
public long findUserCountByNativeQuery(Map<String, Object> parameterMap) {
throw new ActivitiException("LDAP user manager doesn't support querying");
}
@Override
public Boolean checkPassword(final String userId, final String password) {
try {
LDAPTemplate ldapTemplate = new LDAPTemplate(ldapConfigurator);
return ldapTemplate.execute(new LDAPCallBack<Boolean>() {
public Boolean executeInContext(InitialDirContext initialDirContext) {
if (initialDirContext == null) {
return false;
}
// Do the actual search for the user
String userDn = null;
try {
String searchExpression = ldapConfigurator.getLdapQueryBuilder().buildQueryByUserId(ldapConfigurator, userId);
NamingEnumeration< ? > namingEnum = initialDirContext.search(ldapConfigurator.getBaseDn(),
searchExpression, createSearchControls());
while (namingEnum.hasMore()) { // Should be only one
SearchResult result = (SearchResult) namingEnum.next();
userDn = result.getNameInNamespace();
}
namingEnum.close();
} catch (NamingException ne) {
logger.info("Could not authenticate user " + userId + " : " + ne.getMessage(), ne);
return false;
}
// Now we have the user DN, we can need to create a connection it
// ('bind' in ldap lingo)
// to check if the user is valid
if (userDn != null) {
InitialDirContext verificationContext = null;
try {
verificationContext = LDAPConnectionUtil.createDirectoryContext(ldapConfigurator, userDn, password);
} catch (ActivitiException e) {
// Do nothing, an exception will be thrown if the login fails
}
if (verificationContext != null) {
LDAPConnectionUtil.closeDirectoryContext(verificationContext);
return true;
}
}
return false;
}
});
} catch (ActivitiException e) {
logger.info("Could not authenticate user : " + e);
return false;
}
}
protected SearchControls createSearchControls() {
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setTimeLimit(ldapConfigurator.getSearchTimeLimit());
return searchControls;
}
}
/* 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.ldap;
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.UserIdentityManager;
/**
* @author Joram Barrez
*/
public class LDAPUserManagerFactory implements SessionFactory {
protected LDAPConfigurator ldapConfigurator;
public LDAPUserManagerFactory(LDAPConfigurator ldapConfigurator) {
this.ldapConfigurator = ldapConfigurator;
}
@Override
public Class<?> getSessionType() {
return UserIdentityManager.class;
}
@Override
public Session openSession() {
return new LDAPUserManager(ldapConfigurator);
}
public LDAPConfigurator getLdapConfigurator() {
return ldapConfigurator;
}
public void setLdapConfigurator(LDAPConfigurator ldapConfigurator) {
this.ldapConfigurator = ldapConfigurator;
}
}
/* 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.test.ldap;
import java.util.Date;
import org.activiti.engine.impl.persistence.entity.GroupIdentityManager;
import org.activiti.engine.impl.util.ClockUtil;
import org.activiti.engine.test.Deployment;
import org.activiti.ldap.LDAPGroupCache;
import org.activiti.ldap.LDAPGroupCache.LDAPGroupCacheListener;
import org.activiti.ldap.LDAPGroupManagerFactory;
import org.activiti.spring.impl.test.SpringActivitiTestCase;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration("classpath:activiti-context-ldap-group-cache.xml")
public class LdapGroupCacheTest extends SpringActivitiTestCase {
protected TestLDAPGroupCacheListener cacheListener;
@Override
protected void setUp() throws Exception {
super.setUp();
// Set test cache listener
LDAPGroupManagerFactory ldapGroupManagerFactory =
(LDAPGroupManagerFactory) processEngineConfiguration.getSessionFactories().get(GroupIdentityManager.class);
LDAPGroupCache ldapGroupCache = ldapGroupManagerFactory.getLdapGroupCache();
ldapGroupCache.clear();
cacheListener = new TestLDAPGroupCacheListener();
ldapGroupCache.setLdapCacheListener(cacheListener);
}
@Deployment
public void testLdapGroupCacheUsage() {
runtimeService.startProcessInstanceByKey("testLdapGroupCache");
// First task is for Kermit -> cache miss
assertEquals(1, taskService.createTaskQuery().taskCandidateUser("kermit").count());
assertEquals("kermit", cacheListener.getLastCacheMiss());
// Second task is for Pepe -> cache miss
taskService.complete(taskService.createTaskQuery().singleResult().getId());
assertEquals(1, taskService.createTaskQuery().taskCandidateUser("pepe").count());
assertEquals("pepe", cacheListener.getLastCacheMiss());
// Third task is again for kermit -> cache hit
taskService.complete(taskService.createTaskQuery().singleResult().getId());
assertEquals(1, taskService.createTaskQuery().taskCandidateUser("kermit").count());
assertEquals("kermit", cacheListener.getLastCacheHit());
// Foruth task is for fozzie -> cache miss + cache eviction of pepe (LRU)
taskService.complete(taskService.createTaskQuery().singleResult().getId());
assertEquals(1, taskService.createTaskQuery().taskCandidateUser("fozzie").count());
assertEquals("fozzie", cacheListener.getLastCacheMiss());
assertEquals("pepe", cacheListener.getLastCacheEviction());
}
public void testLdapGroupCacheExpiration() {
assertEquals(0, taskService.createTaskQuery().taskCandidateUser("kermit").count());
assertEquals("kermit", cacheListener.getLastCacheMiss());
assertEquals(0, taskService.createTaskQuery().taskCandidateUser("pepe").count());
assertEquals("pepe", cacheListener.getLastCacheMiss());
assertEquals(0, taskService.createTaskQuery().taskCandidateUser("kermit").count());
assertEquals("kermit", cacheListener.getLastCacheHit());
// Test the expiration time of the cache
Date now = new Date();
ClockUtil.setCurrentTime(now);
assertEquals(0, taskService.createTaskQuery().taskCandidateUser("fozzie").count());
assertEquals("fozzie", cacheListener.getLastCacheMiss());
assertEquals("pepe", cacheListener.getLastCacheEviction());
// Moving the clock forward two 45 minues should trigger cache eviction (configured to 30 mins)
ClockUtil.setCurrentTime(new Date(now.getTime() + (45 * 60 * 1000)));
assertEquals(0, taskService.createTaskQuery().taskCandidateUser("fozzie").count());
assertEquals("fozzie", cacheListener.getLastCacheExpiration());
assertEquals("fozzie", cacheListener.getLastCacheEviction());
assertEquals("fozzie", cacheListener.getLastCacheMiss());
}
// Test cache listener
static class TestLDAPGroupCacheListener implements LDAPGroupCacheListener {
protected String lastCacheMiss;
protected String lastCacheHit;
protected String lastCacheEviction;
protected String lastCacheExpiration;
public void cacheMiss(String userId) {
this.lastCacheMiss = userId;
}
public void cacheHit(String userId) {
this.lastCacheHit = userId;
}
public void cacheExpired(String userId) {
this.lastCacheExpiration = userId;
}
public void cacheEviction(String userId) {
this.lastCacheEviction = userId;
}
public String getLastCacheMiss() {
return lastCacheMiss;
}
public void setLastCacheMiss(String lastCacheMiss) {
this.lastCacheMiss = lastCacheMiss;
}
public String getLastCacheHit() {
return lastCacheHit;
}
public void setLastCacheHit(String lastCacheHit) {
this.lastCacheHit = lastCacheHit;
}
public String getLastCacheExpiration() {
return lastCacheExpiration;
}
public void setLastCacheExpiration(String lastCacheExpiration) {
this.lastCacheExpiration = lastCacheExpiration;
}
public String getLastCacheEviction() {
return lastCacheEviction;
}
public void setLastCacheEviction(String lastCacheEviction) {
this.lastCacheEviction = lastCacheEviction;
}
}
}
/* 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.test.ldap;
import org.activiti.engine.test.Deployment;
import org.activiti.spring.impl.test.SpringActivitiTestCase;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration("classpath:activiti-context.xml")
public class LdapIntegrationTest extends SpringActivitiTestCase {
public void testAuthenticationThroughLdap() {
assertTrue(identityService.checkPassword("kermit", "pass"));
assertFalse(identityService.checkPassword("kermit", "blah"));
}
@Deployment
public void testCandidateGroupFetchedThroughLdap() {
runtimeService.startProcessInstanceByKey("testCandidateGroup");
assertEquals(1, taskService.createTaskQuery().count());
assertEquals(1, taskService.createTaskQuery().taskCandidateGroup("Sales").count());
// Pepe is a member of the candidate group and should be able to find the task
assertEquals(1, taskService.createTaskQuery().taskCandidateUser("pepe").count());
// Kermit is a candidate user and should be able to find the task
assertEquals(1, taskService.createTaskQuery().taskCandidateUser("kermit").count());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- Embedded ldap test server -->
<security:ldap-server ldif="classpath:users.ldif" root="o=activiti" manager-dn="uid=admin, ou=users" manager-password="admin"/>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="jobExecutorActivate" value="false" />
<property name="configurators">
<list>
<bean class="org.activiti.ldap.LDAPConfigurator">
<!-- Server connection params -->
<property name="server" value="ldap://localhost" />
<property name="port" value="33389" />
<property name="user" value="uid=admin, ou=users, o=activiti" />
<property name="password" value="pass" />
<!-- Query params -->
<property name="baseDn" value="o=activiti" />
<property name="queryUserByUserId" value="(&amp;(objectClass=inetOrgPerson)(uid={0}))" />
<property name="queryGroupsForUser" value="(&amp;(objectClass=groupOfUniqueNames)(uniqueMember={0}))" />
<!-- Attribute config -->
<property name="userFirstNameAttribute" value="cn" />
<property name="userLastNameAttribute" value="sn" />
<property name="groupIdAttribute" value="cn" />
<property name="groupNameAttribute" value="cn" />
<!-- Group cache settings -->
<property name="groupCacheSize" value="2" /> <!-- Setting it really low for testing purposes -->
<property name="groupCacheExpirationTime" value="1800000" />
</bean>
</list>
</property>
</bean>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<bean id="repositoryService" factory-bean="processEngine"
factory-method="getRepositoryService" />
<bean id="runtimeService" factory-bean="processEngine"
factory-method="getRuntimeService" />
<bean id="taskService" factory-bean="processEngine"
factory-method="getTaskService" />
<bean id="historyService" factory-bean="processEngine"
factory-method="getHistoryService" />
<bean id="managementService" factory-bean="processEngine"
factory-method="getManagementService" />
</beans>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- Embedded ldap test server -->
<security:ldap-server ldif="classpath:users.ldif" root="o=activiti" manager-dn="uid=admin, ou=users" manager-password="admin"/>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="jobExecutorActivate" value="false" />
<property name="configurators">
<list>
<bean class="org.activiti.ldap.LDAPConfigurator">
<!-- Server connection params -->
<property name="server" value="ldap://localhost" />
<property name="port" value="33389" />
<property name="user" value="uid=admin, ou=users, o=activiti" />
<property name="password" value="pass" />
<!-- Query params -->
<property name="baseDn" value="o=activiti" />
<property name="queryUserByUserId" value="(&amp;(objectClass=inetOrgPerson)(uid={0}))" />
<property name="queryGroupsForUser" value="(&amp;(objectClass=groupOfUniqueNames)(uniqueMember={0}))" />
<!-- Attribute config -->
<property name="userFirstNameAttribute" value="cn" />
<property name="userLastNameAttribute" value="sn" />
<property name="groupIdAttribute" value="cn" />
<property name="groupNameAttribute" value="cn" />
</bean>
</list>
</property>
</bean>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<bean id="repositoryService" factory-bean="processEngine"
factory-method="getRepositoryService" />
<bean id="runtimeService" factory-bean="processEngine"
factory-method="getRuntimeService" />
<bean id="taskService" factory-bean="processEngine"
factory-method="getTaskService" />
<bean id="historyService" factory-bean="processEngine"
factory-method="getHistoryService" />
<bean id="managementService" factory-bean="processEngine"
factory-method="getManagementService" />
</beans>
\ No newline at end of file
log4j.rootLogger=INFO, CA
# ConsoleAppender
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n
log4j.logger.org.apache.ibatis.level=INFO
log4j.logger.javax.activation.level=INFO
<?xml version="1.0" encoding="UTF-8"?>
<definitions id="taskAssigneeExample"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="ldap">
<process id="testLdapGroupCache">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask1" />
<userTask id="theTask1">
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>user(kermit), group(Sales)</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow2" sourceRef="theTask1" targetRef="theTask2" />
<userTask id="theTask2">
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>user(pepe), group(Sales)</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow3" sourceRef="theTask2" targetRef="theTask3" />
<userTask id="theTask3">
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>user(kermit), group(Sales)</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow4" sourceRef="theTask3" targetRef="theTask4" />
<userTask id="theTask4">
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>user(fozzie), group(Sales)</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow5" sourceRef="theTask3" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions id="taskAssigneeExample"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="ldap">
<process id="testCandidateGroup">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />
<userTask id="theTask">
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>user(kermit), group(Sales)</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow2" sourceRef="theTask" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
# Based on the example LDIF file at http://krams915.blogspot.be/2011/01/spring-security-mvc-using-embedded-ldap.html
# Root
dn: o=activiti
objectClass: organization
objectClass: extensibleObject
objectClass: top
o: activiti
# Users root
dn: ou=users,o=activiti
objectClass: extensibleObject
objectClass: organizationalUnit
objectClass: top
ou: users
# Groups root
dn: ou=groups,o=activiti
objectClass: extensibleObject
objectClass: organizationalUnit
objectClass: top
ou: groups
# Actual groups
dn: cn=User,ou=groups,o=activiti
objectClass: groupOfUniqueNames
objectClass: top
cn: User
uniqueMember: uid=kermit, ou=users,o=activiti
uniqueMember: uid=pepe, ou=users,o=activiti
uniqueMember: uid=gonzo, ou=users,o=activiti
uniqueMember: uid=fozzie, ou=users,o=activiti
dn: cn=Admin,ou=groups,o=activiti
objectClass: groupOfUniqueNames
objectClass: top
cn: Admin
uniqueMember: uid=kermit, ou=users,o=activiti
uniqueMember: uid=fozzie, ou=users,o=activiti
dn: cn=Sales,ou=groups,o=activiti
objectClass: groupOfUniqueNames
objectClass: top
cn: Sales
uniqueMember: uid=pepe, ou=users,o=activiti
uniqueMember: uid=gonzo, ou=users,o=activiti
# Actual users
dn: uid=admin,ou=users,o=activiti
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: admin
sn: admin
uid: admin
userPassword:: cGFzcw==
dn: uid=pepe, ou=users,o=activiti
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: Pepe the King Prawn
sn: the King Prawn
uid: pepe
userPassword:: cGFzcw==
dn: uid=fozzie,ou=users,o=activiti
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: Fozzie Bear
sn: Bear
uid: fozzie
userPassword:: cGFzcw==
dn: uid=kermit,ou=users,o=activiti
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: Kermit The Frog
sn: The Frog
uid: kermit
userPassword:: cGFzcw==
dn: uid=gonzo,ou=users,o=activiti
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: Gonzo The Great
sn: The Great
uid: gonzo
userPassword:: cGFzcw==
\ No newline at end of file
......@@ -31,6 +31,7 @@ import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.Job;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Attachment;
import org.activiti.engine.task.Comment;
......@@ -57,6 +58,7 @@ import org.activiti.rest.api.history.HistoricProcessInstanceResponse;
import org.activiti.rest.api.history.HistoricTaskInstanceResponse;
import org.activiti.rest.api.history.HistoricVariableInstanceResponse;
import org.activiti.rest.api.identity.RestIdentityLink;
import org.activiti.rest.api.management.JobResponse;
import org.activiti.rest.api.management.TableResponse;
import org.activiti.rest.api.repository.DeploymentResourceResponse;
import org.activiti.rest.api.repository.DeploymentResourceResponse.DeploymentResourceType;
......@@ -401,6 +403,7 @@ public class RestResponseFactory {
return result;
}
@SuppressWarnings("deprecation")
public HistoricProcessInstanceResponse createHistoricProcessInstanceResponse(SecuredResource securedResource, HistoricProcessInstance processInstance) {
HistoricProcessInstanceResponse result = new HistoricProcessInstanceResponse();
result.setBusinessKey(processInstance.getBusinessKey());
......@@ -515,6 +518,32 @@ public class RestResponseFactory {
return result;
}
public JobResponse createJobResponse(SecuredResource securedResource, Job job) {
JobResponse response = new JobResponse();
response.setId(job.getId());
response.setDueDate(job.getDuedate());
response.setExceptionMessage(job.getExceptionMessage());
response.setExecutionId(job.getExecutionId());
response.setProcessDefinitionId(job.getProcessDefinitionId());
response.setProcessInstanceId(job.getProcessInstanceId());
response.setRetries(job.getRetries());
response.setUrl(securedResource.createFullResourceUrl(RestUrls.URL_JOB, job.getId()));
if(job.getProcessDefinitionId() != null) {
response.setProcessDefinitionUrl(securedResource.createFullResourceUrl(RestUrls.URL_PROCESS_DEFINITION, job.getProcessDefinitionId()));
}
if(job.getProcessInstanceId() != null) {
response.setProcessInstanceUrl(securedResource.createFullResourceUrl(RestUrls.URL_PROCESS_INSTANCE, job.getProcessInstanceId()));
}
if(job.getExecutionId() != null) {
response.setExecutionUrl(securedResource.createFullResourceUrl(RestUrls.URL_EXECUTION, job.getExecutionId()));
}
return response;
}
/**
* Called once when the converters need to be initialized. Override of custom conversion
......@@ -529,6 +558,4 @@ public class RestResponseFactory {
variableConverters.add(new BooleanRestVariableConverter());
variableConverters.add(new DateRestVariableConverter());
}
}
......@@ -56,6 +56,7 @@ public final class RestUrls {
public static final String SEGMENT_TABLES = "tables";
public static final String SEGMENT_COLUMNS = "columns";
public static final String SEGMENT_DATA = "data";
public static final String SEGMENT_JOBS = "jobs";
/**
* URL template for the deployment collection: <i>repository/deployments</i>
......@@ -321,7 +322,15 @@ public final class RestUrls {
*/
public static final String[] URL_TABLE_DATA = {SEGMENT_MANAGEMENT_RESOURCES, SEGMENT_TABLES, "{0}", SEGMENT_DATA};
/**
* URL template for a single job: <i>management/jobs/{0:jobId}</i>
*/
public static final String[] URL_JOB = {SEGMENT_MANAGEMENT_RESOURCES, SEGMENT_JOBS, "{0}"};
/**
* URL template for the collection of jobs: <i>management/jobs</i>
*/
public static final String[] URL_JOB_COLLECTION = {SEGMENT_MANAGEMENT_RESOURCES, SEGMENT_JOBS};
/**
* Creates an url based on the passed fragments and replaces any placeholders with the given arguments. The
......
/* 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.rest.api.management;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.runtime.Job;
import org.activiti.rest.api.ActivitiUtil;
import org.activiti.rest.api.RestActionRequest;
import org.activiti.rest.api.SecuredResource;
import org.activiti.rest.application.ActivitiRestServicesApplication;
import org.restlet.data.Status;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
/**
* @author Frederik Heremans
*/
public class JobResource extends SecuredResource {
private static final String EXECUTE_ACTION = "execute";
@Get
public JobResponse getJob() {
if (authenticate() == false)
return null;
Job job = getJobFromResponse();
JobResponse response = getApplication(ActivitiRestServicesApplication.class).getRestResponseFactory()
.createJobResponse(this, job);
return response;
}
@Delete
public void deleteJob() {
if (authenticate() == false)
return;
String jobId = getAttribute("jobId");
if (jobId == null) {
throw new ActivitiIllegalArgumentException("The jobId cannot be null");
}
try {
ActivitiUtil.getManagementService().deleteJob(jobId);
} catch(ActivitiObjectNotFoundException aonfe) {
// Re-throw to have consistent error-messaging acrosse REST-api
throw new ActivitiObjectNotFoundException("Could not find a job with id '" + jobId + "'.", Job.class);
}
setStatus(Status.SUCCESS_NO_CONTENT);
}
@Post
public void executeJobAction(RestActionRequest actionRequest) {
if (authenticate() == false)
return;
String jobId = getAttribute("jobId");
if (jobId == null) {
throw new ActivitiIllegalArgumentException("The jobId cannot be null");
}
if(actionRequest == null || ! EXECUTE_ACTION.equals(actionRequest.getAction())) {
throw new ActivitiIllegalArgumentException("Invalid action, only 'execute' is supported.");
}
try {
ActivitiUtil.getManagementService().executeJob(jobId);
} catch(ActivitiObjectNotFoundException aonfe) {
// Re-throw to have consistent error-messaging acrosse REST-api
throw new ActivitiObjectNotFoundException("Could not find a job with id '" + jobId + "'.", Job.class);
}
setStatus(Status.SUCCESS_NO_CONTENT);
}
protected Job getJobFromResponse() {
String jobId = getAttribute("jobId");
if (jobId == null) {
throw new ActivitiIllegalArgumentException("The jobId cannot be null");
}
Job job = ActivitiUtil.getManagementService().createJobQuery().jobId(jobId).singleResult();
if (job == null) {
throw new ActivitiObjectNotFoundException("Could not find a job with id '" + jobId + "'.", Job.class);
}
return job;
}
}
/* 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.rest.api.management;
import java.util.Date;
/**
* @author Frederik Heremans
*/
public class JobResponse {
protected String id;
protected String url;
protected String processInstanceId;
protected String processInstanceUrl;
protected String processDefinitionId;
protected String processDefinitionUrl;
protected String executionId;
protected String executionUrl;
protected Integer retries;
protected String exceptionMessage;
protected Date dueDate;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getProcessInstanceId() {
return processInstanceId;
}
public void setProcessInstanceId(String processInstanceId) {
this.processInstanceId = processInstanceId;
}
public String getProcessInstanceUrl() {
return processInstanceUrl;
}
public void setProcessInstanceUrl(String processInstanceUrl) {
this.processInstanceUrl = processInstanceUrl;
}
public String getProcessDefinitionId() {
return processDefinitionId;
}
public void setProcessDefinitionId(String processDefinitionId) {
this.processDefinitionId = processDefinitionId;
}
public String getProcessDefinitionUrl() {
return processDefinitionUrl;
}
public void setProcessDefinitionUrl(String processDefinitionUrl) {
this.processDefinitionUrl = processDefinitionUrl;
}
public String getExecutionId() {
return executionId;
}
public void setExecutionId(String executionId) {
this.executionId = executionId;
}
public String getExecutionUrl() {
return executionUrl;
}
public void setExecutionUrl(String executionUrl) {
this.executionUrl = executionUrl;
}
public Integer getRetries() {
return retries;
}
public void setRetries(Integer retries) {
this.retries = retries;
}
public String getExceptionMessage() {
return exceptionMessage;
}
public void setExceptionMessage(String exceptionMessage) {
this.exceptionMessage = exceptionMessage;
}
public Date getDueDate() {
return dueDate;
}
public void setDueDate(Date dueDate) {
this.dueDate = dueDate;
}
}
......@@ -52,6 +52,7 @@ import org.activiti.rest.api.legacy.process.LegacyProcessInstanceResource;
import org.activiti.rest.api.legacy.process.LegacyProcessInstancesResource;
import org.activiti.rest.api.legacy.process.ProcessDefinitionsResource;
import org.activiti.rest.api.legacy.task.LegacyTaskResource;
import org.activiti.rest.api.management.JobResource;
import org.activiti.rest.api.management.TableCollectionResource;
import org.activiti.rest.api.management.TableColumnsResource;
import org.activiti.rest.api.management.TableDataResource;
......@@ -158,6 +159,7 @@ public class RestServicesInit {
router.attach("/management/tables/{tableName}", TableResource.class);
router.attach("/management/tables/{tableName}/columns", TableColumnsResource.class);
router.attach("/management/tables/{tableName}/data", TableDataResource.class);
router.attach("/management/jobs/{jobId}", JobResource.class);
router.attach("/query/tasks", TaskQueryResource.class);
router.attach("/query/process-instances", ProcessInstanceQueryResource.class);
......
package org.activiti.rest.api.management;
import java.util.Calendar;
import org.activiti.engine.impl.util.ClockUtil;
import org.activiti.engine.runtime.Job;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.test.Deployment;
import org.activiti.rest.BaseRestTestCase;
import org.activiti.rest.api.RestUrls;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ObjectNode;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.resource.ClientResource;
import org.restlet.resource.ResourceException;
/**
* Test for all REST-operations related to the Job collection and a single
* job resource.
*
* @author Frederik Heremans
*/
public class JobResourceTest extends BaseRestTestCase {
/**
* Test getting a single job.
*/
@Deployment(resources = {"org/activiti/rest/api/management/JobResourceTest.testTimerProcess.bpmn20.xml"})
public void testGetJob() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("timerProcess");
Job timerJob = managementService.createJobQuery().processInstanceId(processInstance.getId()).singleResult();
assertNotNull(timerJob);
Calendar now = Calendar.getInstance();
now.set(Calendar.MILLISECOND, 0);
ClockUtil.setCurrentTime(now.getTime());
ClientResource client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB, timerJob.getId()));
Representation response = client.get();
assertEquals(Status.SUCCESS_OK, client.getResponse().getStatus());
JsonNode responseNode = objectMapper.readTree(response.getStream());
assertNotNull(responseNode);
assertEquals(timerJob.getId(), responseNode.get("id").getTextValue());
assertEquals(timerJob.getExceptionMessage(), responseNode.get("exceptionMessage").getTextValue());
assertEquals(timerJob.getExecutionId(), responseNode.get("executionId").getTextValue());
assertEquals(timerJob.getProcessDefinitionId(), responseNode.get("processDefinitionId").getTextValue());
assertEquals(timerJob.getProcessInstanceId(), responseNode.get("processInstanceId").getTextValue());
assertEquals(timerJob.getRetries(), responseNode.get("retries").getIntValue());
assertEquals(timerJob.getDuedate(), getDateFromISOString(responseNode.get("dueDate").getTextValue()));
}
/**
* Test getting an unexisting job.
*/
public void testGetUnexistingJob() throws Exception {
ClientResource client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB, "unexistingjob"));
try {
client.get();
fail("Exception expected");
} catch(ResourceException expected) {
assertEquals(Status.CLIENT_ERROR_NOT_FOUND, expected.getStatus());
assertEquals("Could not find a job with id 'unexistingjob'.", expected.getStatus().getDescription());
}
}
/**
* Test executing a single job.
*/
@Deployment(resources = {"org/activiti/rest/api/management/JobResourceTest.testTimerProcess.bpmn20.xml"})
public void testExecuteJob() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("timerProcess");
Job timerJob = managementService.createJobQuery().processInstanceId(processInstance.getId()).singleResult();
assertNotNull(timerJob);
ObjectNode requestNode = objectMapper.createObjectNode();
requestNode.put("action", "execute");
ClientResource client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB, timerJob.getId()));
Representation response = client.post(requestNode);
assertEquals(Status.SUCCESS_NO_CONTENT, client.getResponse().getStatus());
assertEquals(0L, response.getSize());
// Job should be executed
assertNull(managementService.createJobQuery().processInstanceId(processInstance.getId()).singleResult());
}
/**
* Test executing an unexisting job.
*/
@Deployment(resources = {"org/activiti/rest/api/management/JobResourceTest.testTimerProcess.bpmn20.xml"})
public void testExecuteUnexistingJob() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("timerProcess");
Job timerJob = managementService.createJobQuery().processInstanceId(processInstance.getId()).singleResult();
assertNotNull(timerJob);
ObjectNode requestNode = objectMapper.createObjectNode();
requestNode.put("action", "execute");
ClientResource client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB, "unexistingjob"));
try {
client.post(requestNode);
fail("Exception expected");
} catch(ResourceException expected) {
assertEquals(Status.CLIENT_ERROR_NOT_FOUND, expected.getStatus());
assertEquals("Could not find a job with id 'unexistingjob'.", expected.getStatus().getDescription());
}
}
/**
* Test executing an unexisting job.
*/
@Deployment(resources = {"org/activiti/rest/api/management/JobResourceTest.testTimerProcess.bpmn20.xml"})
public void testIllegalActionOnJob() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("timerProcess");
Job timerJob = managementService.createJobQuery().processInstanceId(processInstance.getId()).singleResult();
assertNotNull(timerJob);
ObjectNode requestNode = objectMapper.createObjectNode();
requestNode.put("action", "unexistinAction");
ClientResource client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB, timerJob.getId()));
try {
client.post(requestNode);
fail("Exception expected");
} catch(ResourceException expected) {
assertEquals(Status.CLIENT_ERROR_BAD_REQUEST, expected.getStatus());
assertEquals("Invalid action, only 'execute' is supported.", expected.getStatus().getDescription());
}
}
/**
* Test deleting a single job.
*/
@Deployment(resources = {"org/activiti/rest/api/management/JobResourceTest.testTimerProcess.bpmn20.xml"})
public void testDeleteJob() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("timerProcess");
Job timerJob = managementService.createJobQuery().processInstanceId(processInstance.getId()).singleResult();
assertNotNull(timerJob);
ClientResource client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB, timerJob.getId()));
Representation response = client.delete();
assertEquals(Status.SUCCESS_NO_CONTENT, client.getResponse().getStatus());
assertEquals(0L, response.getSize());
// Job should be deleted
assertNull(managementService.createJobQuery().processInstanceId(processInstance.getId()).singleResult());
}
/**
* Test getting an unexisting job.
*/
public void testDeleteUnexistingJob() throws Exception {
ClientResource client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_JOB, "unexistingjob"));
try {
client.delete();
fail("Exception expected");
} catch(ResourceException expected) {
assertEquals(Status.CLIENT_ERROR_NOT_FOUND, expected.getStatus());
assertEquals("Could not find a job with id 'unexistingjob'.", expected.getStatus().getDescription());
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="timerProcess">
<startEvent id="start" />
<sequenceFlow id="flow1" sourceRef="start" targetRef="task" />
<userTask id="task" />
<boundaryEvent id="escalationTimer" cancelActivity="true" attachedToRef="task">
<timerEventDefinition>
<timeDuration>PT4H</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<sequenceFlow id="flow3" sourceRef="escalationTimer" targetRef="afterTimerTest" />
<userTask id="afterTimerTest" />
<sequenceFlow id="flow4" sourceRef="afterTimerTest" targetRef="end" />
<sequenceFlow id="flow2" sourceRef="task" targetRef="end" />
<endEvent id="end" />
</process>
</definitions>
\ No newline at end of file
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<name>Activiti - Spring</name>
<artifactId>activiti-spring</artifactId>
<name>Activiti - Spring</name>
<artifactId>activiti-spring</artifactId>
<parent>
<groupId>org.activiti</groupId>
<artifactId>activiti-root</artifactId>
<relativePath>../..</relativePath>
<version>5.13-SNAPSHOT</version>
</parent>
<parent>
<groupId>org.activiti</groupId>
<artifactId>activiti-root</artifactId>
<relativePath>../..</relativePath>
<version>5.13-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.subethamail</groupId>
<artifactId>subethasmtp-wiser</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.subethamail</groupId>
<artifactId>subethasmtp-wiser</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
<profiles>
<profile>
<id>check</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>delete-test-sources</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<delete dir="src/test/java/org/activiti/engine/test"/>
<delete dir="src/test/resources/org/activiti/engine/test"/>
<delete dir="src/test/java/org/activiti/examples"/>
<delete dir="src/test/resources/org/activiti/examples"/>
<delete dir="src/test/java/org/activiti/standalone"/>
<delete dir="src/test/resources/org/activiti/standalone"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>checkspring</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>copy-test-sources-from-engine</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<delete dir="src/test/java/org/activiti/engine/test"/>
<delete dir="src/test/resources/org/activiti/engine/test"/>
<delete dir="src/test/java/org/activiti/examples"/>
<delete dir="src/test/resources/org/activiti/examples"/>
<delete dir="src/test/java/org/activiti/standalone"/>
<delete dir="src/test/resources/org/activiti/standalone"/>
<copy todir="src/test/java" overwrite="true">
<fileset dir="../activiti-engine/src/test/java" />
</copy>
<copy todir="src/test/resources" overwrite="true">
<fileset dir="../activiti-engine/src/test/resources" />
</copy>
</tasks>
</configuration>
</execution>
<execution>
<id>delete-test-sources-after</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<delete dir="src/test/java/org/activiti/engine/test"/>
<delete dir="src/test/resources/org/activiti/engine/test"/>
<delete dir="src/test/java/org/activiti/examples"/>
<delete dir="src/test/resources/org/activiti/examples"/>
<delete dir="src/test/java/org/activiti/standalone"/>
<delete dir="src/test/resources/org/activiti/standalone"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemProperties>
<property>
<name>process.engine.initializer</name>
<value>org.activiti.spring.SpringProcessEngineInitializer</value>
</property>
</systemProperties>
<excludes>
<exclude>org/activiti/standalone/**</exclude>
<exclude>**/*TestCase.java</exclude>
<exclude>**/ActivitiRuleJunit4Test.java</exclude><!-- Can't run in Spring since ActivitiRule must be used different in Spring -->
<exclude>**/CompetingJobAcquisitionTest.java</exclude> <!-- http://jira.codehaus.org/browse/ACT-234 -->
<exclude>**/WSDLImporterTest.java</exclude> <!-- http://jira.codehaus.org/browse/ACT-315 -->
<exclude>**/JobExecutorTest.java</exclude> <!-- http://jira.codehaus.org/browse/ACT-427 -->
<exclude>**/HistoricTaskInstanceUpdateTest.java</exclude> <!-- http://jira.codehaus.org/browse/ACT-485 -->
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>distro</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<repositories>
<!-- This repo declaration is here for as this will be part of the distro -->
<repository>
<id>activiti</id>
<name>Activiti</name>
<url>https://maven.alfresco.com/nexus/content/repositories/activiti/</url>
</repository>
</repositories>
<profiles>
<profile>
<id>check</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>delete-test-sources</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<delete dir="src/test/java/org/activiti/engine/test" />
<delete dir="src/test/resources/org/activiti/engine/test" />
<delete dir="src/test/java/org/activiti/examples" />
<delete dir="src/test/resources/org/activiti/examples" />
<delete dir="src/test/java/org/activiti/standalone" />
<delete dir="src/test/resources/org/activiti/standalone" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>checkspring</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>copy-test-sources-from-engine</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<delete dir="src/test/java/org/activiti/engine/test" />
<delete dir="src/test/resources/org/activiti/engine/test" />
<delete dir="src/test/java/org/activiti/examples" />
<delete dir="src/test/resources/org/activiti/examples" />
<delete dir="src/test/java/org/activiti/standalone" />
<delete dir="src/test/resources/org/activiti/standalone" />
<copy todir="src/test/java" overwrite="true">
<fileset dir="../activiti-engine/src/test/java" />
</copy>
<copy todir="src/test/resources" overwrite="true">
<fileset dir="../activiti-engine/src/test/resources" />
</copy>
</tasks>
</configuration>
</execution>
<execution>
<id>delete-test-sources-after</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<delete dir="src/test/java/org/activiti/engine/test" />
<delete dir="src/test/resources/org/activiti/engine/test" />
<delete dir="src/test/java/org/activiti/examples" />
<delete dir="src/test/resources/org/activiti/examples" />
<delete dir="src/test/java/org/activiti/standalone" />
<delete dir="src/test/resources/org/activiti/standalone" />
</tasks>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemProperties>
<property>
<name>process.engine.initializer</name>
<value>org.activiti.spring.SpringProcessEngineInitializer</value>
</property>
</systemProperties>
<excludes>
<exclude>org/activiti/standalone/**</exclude>
<exclude>**/*TestCase.java</exclude>
<exclude>**/ActivitiRuleJunit4Test.java</exclude><!-- Can't run in
Spring since ActivitiRule must be used different in Spring -->
<exclude>**/CompetingJobAcquisitionTest.java</exclude> <!-- http://jira.codehaus.org/browse/ACT-234 -->
<exclude>**/WSDLImporterTest.java</exclude> <!-- http://jira.codehaus.org/browse/ACT-315 -->
<exclude>**/JobExecutorTest.java</exclude> <!-- http://jira.codehaus.org/browse/ACT-427 -->
<exclude>**/HistoricTaskInstanceUpdateTest.java</exclude> <!-- http://jira.codehaus.org/browse/ACT-485 -->
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>distro</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<repositories>
<!-- This repo declaration is here for as this will be part of the distro -->
<repository>
<id>activiti</id>
<name>Activiti</name>
<url>https://maven.alfresco.com/nexus/content/repositories/activiti/</url>
</repository>
</repositories>
</project>
......@@ -699,13 +699,13 @@
<module>modules/activiti-webapp-explorer2</module>
<module>modules/activiti-rest</module>
<module>modules/activiti-webapp-rest2</module>
<module>modules/activiti-webapp-angular</module>
<module>modules/activiti-spring</module>
<module>modules/activiti-cxf</module>
<module>modules/activiti-mule</module>
<module>modules/activiti-camel</module>
<module>modules/activiti-cdi</module>
<module>modules/activiti-osgi</module>
<module>modules/activiti-ldap</module>
</modules>
<build>
<plugins>
......@@ -791,12 +791,12 @@
<module>modules/activiti-rest</module>
<module>modules/activiti-webapp-rest2</module>
<module>modules/activiti-webapp-explorer2</module>
<module>modules/activiti-webapp-angular</module>
<module>modules/activiti-cxf</module>
<module>modules/activiti-osgi</module>
<module>modules/activiti-camel</module>
<module>modules/activiti-mule</module>
<module>modules/activiti-cdi</module>
<module>modules/activiti-ldap</module>
</modules>
</profile>
<profile>
......
......@@ -4006,6 +4006,192 @@ Only the attachment name is required to create a new attachment.
</section>
<section>
<title>Jobs</title>
<section>
<title>Get a single job</title>
<para>
<programlisting>GET management/jobs/{jobId}</programlisting>
</para>
<para>
<table>
<title>URL parameters</title>
<tgroup cols='3'>
<thead>
<row>
<entry>Parameter</entry>
<entry>Required</entry>
<entry>Value</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>jobId</entry>
<entry>Yes</entry>
<entry>String</entry>
<entry>The id of the job to get.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
<emphasis role="bold">Success response body:</emphasis>
<programlisting>
{
"id":"8",
"url":"http://localhost:8182/management/jobs/8",
"processInstanceId":"5",
"processInstanceUrl":"http://localhost:8182/runtime/process-instances/5",
"processDefinitionId":"timerProcess:1:4",
"processDefinitionUrl":"http://localhost:8182/repository/process-definitions/timerProcess%3A1%3A4",
"executionId":"7",
"executionUrl":"http://localhost:8182/runtime/executions/7",
"retries":3,
"exceptionMessage":null,
"dueDate":"2013-06-04T22:05:05.474+0000"
}</programlisting>
<table>
<title>Response codes</title>
<tgroup cols='2'>
<thead>
<row>
<entry>Response code</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>200</entry>
<entry>Indicates the job exists and is returned.</entry>
</row>
<row>
<entry>404</entry>
<entry>Indicates the requested job does not exist.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
</section>
<section>
<title>Delete a job</title>
<para>
<programlisting>DELETE management/jobs/{jobId}</programlisting>
</para>
<para>
<table>
<title>URL parameters</title>
<tgroup cols='3'>
<thead>
<row>
<entry>Parameter</entry>
<entry>Required</entry>
<entry>Value</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>jobId</entry>
<entry>Yes</entry>
<entry>String</entry>
<entry>The id of the job to delete.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
<table>
<title>Response codes</title>
<tgroup cols='2'>
<thead>
<row>
<entry>Response code</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>204</entry>
<entry>Indicates the job was found and has been deleted. Response-body is intentionally empty.</entry>
</row>
<row>
<entry>404</entry>
<entry>Indicates the requested job was not found.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
</section>
<section>
<title>Execute a single job</title>
<para>
<programlisting>PUT managemebt/jobs/{jobId}</programlisting>
</para>
<para>
<emphasis role="bold">Body JSON:</emphasis>
<programlisting>
{
"action" : "execute"
}</programlisting>
<table>
<title>JSON Body parameters</title>
<tgroup cols='2'>
<thead>
<row>
<entry>Parameter</entry>
<entry>Description</entry>
<entry>Required</entry>
</row>
</thead>
<tbody>
<row>
<entry>action</entry>
<entry>Action to perform. Only <literal>execute</literal> is supported.</entry>
<entry>Yes</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
<table>
<title>Response codes</title>
<tgroup cols='2'>
<thead>
<row>
<entry>Response code</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>204</entry>
<entry>Indicates the job was executed. Response-body is intentionally empty.</entry>
</row>
<row>
<entry>404</entry>
<entry>Indicates the requested job was not found.</entry>
</row>
<row>
<entry>500</entry>
<entry>Indicates the an exception occured while executing the job. The status-description contains additional detail about the error. The full error-stacktrace can be fetched later on if needed.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
</section>
</section>
<!-- Legacy -->
<section>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册