1 package com.atlassian.jira.workflow;
2
3 import java.util.HashMap;
4 import java.util.Iterator;
5 import java.util.List;
6 import java.util.Map;
7
8 import org.apache.commons.lang.exception.NestableRuntimeException;
9 import org.apache.log4j.Logger;
10
11 import webwork.action.ServletActionContext;
12
13 import com.atlassian.jira.ComponentManager;
14 import com.atlassian.jira.ManagerFactory;
15 import com.atlassian.jira.issue.Issue;
16 import com.atlassian.jira.issue.operation.IssueOperations;
17 import com.atlassian.jira.plugin.MakeConditionHelper;
18 import com.atlassian.jira.plugin.webfragment.JiraWebInterfaceManager;
19 import com.atlassian.jira.plugin.webfragment.model.JiraHelper;
20 import com.atlassian.jira.security.JiraAuthenticationContext;
21 import com.atlassian.plugin.web.Condition;
22 import com.atlassian.plugin.web.conditions.ConditionLoadingException;
23 import com.opensymphony.user.User;
24 import com.opensymphony.workflow.InvalidEntryStateException;
25 import com.opensymphony.workflow.InvalidInputException;
26 import com.opensymphony.workflow.InvalidRoleException;
27 import com.opensymphony.workflow.Workflow;
28 import com.opensymphony.workflow.config.Configuration;
29 import com.opensymphony.workflow.loader.ActionDescriptor;
30 import com.opensymphony.workflow.loader.StepDescriptor;
31 import com.opensymphony.workflow.loader.WorkflowDescriptor;
32
33
34
35
36
37
38
39
40 public class ExtendedWorkflowManager extends OSWorkflowManager {
41
42 private static final Logger log = Logger.getLogger(ExtendedWorkflowManager.class);
43
44 protected JiraAuthenticationContext authenticationContext;
45
46 public ExtendedWorkflowManager(DraftWorkflowStore draftWorkflowStore) {
47 super(draftWorkflowStore);
48 }
49
50 public ExtendedWorkflowManager(Configuration configuration, DraftWorkflowStore draftWorkflowStore) {
51 super(configuration, draftWorkflowStore);
52 }
53
54
55
56
57
58
59
60 protected JiraWorkflow getJiraWorkflow(Issue _issue) throws IllegalArgumentException, WorkflowException {
61 Long projectId = _issue.getProjectObject().getId();
62 String issueTypeId = _issue.getIssueType().getString("id");
63 JiraWorkflow jiraWorkflow = getWorkflow(projectId, issueTypeId);
64
65 if (jiraWorkflow == null) {
66 throw new IllegalArgumentException("Cannot find workflow for project with id '" + projectId + "' and issue type with id '" + issueTypeId + "'.");
67 }
68 return jiraWorkflow;
69 }
70
71
72
73
74
75
76 public void validateIssue(String remoteUserName, Map fields) throws WorkflowException {
77 try {
78
79 Issue issue = (Issue) fields.get("issue");
80 final Workflow workflow = makeWorkflow(remoteUserName);
81 final ActionDescriptor actionDescriptor = getEditActionDescriptor(issue);
82 if (actionDescriptor != null) {
83 long wfId = issue.getLong("workflowId").longValue();
84 workflow.doAction(wfId, actionDescriptor.getId(), fields);
85 }
86
87 } catch (InvalidRoleException e) {
88 log.error("Error occurred while creating issue.", e);
89 throw new WorkflowException(e);
90 } catch (InvalidInputException e) {
91 log.error("Error occurred while creating issue.", e);
92 throw new WorkflowException(e);
93 } catch (InvalidEntryStateException e) {
94 log.error("Error occurred while creating issue.", e);
95 throw new WorkflowException(e);
96 } catch (com.opensymphony.workflow.WorkflowException e) {
97 log.error("Error occured while creating issue.", e);
98 throw new WorkflowException(e);
99 } catch (ClassCastException e) {
100 String message = "Error occurred while creating issue. This could be due to a plugin being incompatible with this version of JIRA. For more details please consult the logs, and see: "
101 + "http://confluence.atlassian.com/x/3McB";
102 log.error(message, e);
103 throw new WorkflowException(message, e);
104 }
105 }
106
107 public ActionDescriptor getEditActionDescriptor(Issue _issue) throws WorkflowException {
108 ActionDescriptor actionDescriptor = null;
109 JiraWorkflow jiraWorkflow = getJiraWorkflow(_issue);
110 WorkflowDescriptor workflowDescriptor = jiraWorkflow.getDescriptor();
111 List globalActions = workflowDescriptor.getGlobalActions();
112 if (globalActions != null) {
113 for (Iterator iterator = globalActions.iterator(); iterator.hasNext();) {
114 actionDescriptor = (ActionDescriptor) iterator.next();
115 Map metadata = actionDescriptor.getMetaAttributes();
116 if (metadata.containsKey(JiraWorkflowMetaAttributes.JIRA_META_ATTRIBUTE_OPERATION_ID)) {
117 String operationId = (String) metadata.get(JiraWorkflowMetaAttributes.JIRA_META_ATTRIBUTE_OPERATION_ID);
118 boolean isEditAction = (operationId.equals(IssueOperations.EDIT_ISSUE_OPERATION.getId().toString()));
119 if (isEditAction) {
120 break;
121 }
122 }
123 actionDescriptor = null;
124 }
125 }
126 return actionDescriptor;
127 }
128
129 public static boolean isEditOperation(ActionDescriptor _actionDescriptor) {
130 boolean isEditOperation = false;
131 Map metadata = _actionDescriptor.getMetaAttributes();
132 String operationId = (String) metadata.get(JiraWorkflowMetaAttributes.JIRA_META_ATTRIBUTE_OPERATION_ID);
133 isEditOperation = (operationId.equals(IssueOperations.EDIT_ISSUE_OPERATION.getId().toString()));
134 return isEditOperation;
135 }
136
137 public static Long getOperationId(ActionDescriptor _actionDescriptor) {
138 Map metadata = _actionDescriptor.getMetaAttributes();
139 if (metadata.containsKey(JiraWorkflowMetaAttributes.JIRA_META_ATTRIBUTE_OPERATION_ID)) {
140 String operationId = (String) metadata.get(JiraWorkflowMetaAttributes.JIRA_META_ATTRIBUTE_OPERATION_ID);
141 if (operationId!=null) {
142 return new Long(operationId);
143 }
144 }
145 return null;
146 }
147
148
149
150
151
152
153 public boolean isDeletable(final Issue _issue) {
154 boolean isDeletable = true;
155
156 try {
157 JiraWorkflow workflow = getWorkflow(_issue.getProjectObject().getId(), _issue.getIssueTypeObject().getId());
158 final String status = _issue.getStatusObject().getId();
159 if (status != null)
160 {
161 StepDescriptor currentStep = workflow.getLinkedStep(ManagerFactory.getConstantsManager().getStatus(status));
162 String attribute = (String) currentStep.getMetaAttributes().get(JiraWorkflowMetaAttributes.JIRA_META_ATTRIBUTE_DELETE_ISSUE);
163
164 if (attribute == null) {
165 ActionDescriptor actionDescriptor = getEditActionDescriptor(_issue);
166 if (actionDescriptor != null) {
167 attribute = (String)actionDescriptor.getMetaAttributes().get(JiraWorkflowMetaAttributes.JIRA_META_ATTRIBUTE_DELETE_ISSUE);
168 }
169 }
170
171 if (attribute != null) {
172
173 if (attribute.equalsIgnoreCase("true") || attribute.equalsIgnoreCase("false")) {
174 isDeletable = new Boolean(attribute).booleanValue();
175 } else {
176 Condition condition = MakeConditionHelper.getInstance().loadCondition(attribute);
177 if (condition != null) {
178 Map context = new HashMap();
179 User user = getAuthenticationContext().getUser();
180 JiraHelper jh = new JiraHelper(ServletActionContext.getRequest(), _issue.getProjectObject().getGenericValue());
181 context.put(JiraWebInterfaceManager.CONTEXT_KEY_USER, user);
182 context.put(JiraWebInterfaceManager.CONTEXT_KEY_HELPER, jh);
183 context.put("issue", _issue);
184 isDeletable = condition.shouldDisplay(context);
185 }
186 }
187 }
188 }
189 } catch (ConditionLoadingException cle) {
190 log.warn(cle.getLocalizedMessage());
191 isDeletable = true;
192 } catch (WorkflowException e) {
193 throw new NestableRuntimeException(e + " when trying to access workflow for issue " + _issue, e);
194 }
195 return isDeletable;
196 }
197
198 public JiraAuthenticationContext getAuthenticationContext() {
199 if (authenticationContext == null) {
200 authenticationContext = (JiraAuthenticationContext) ComponentManager.getComponentInstanceOfType(JiraAuthenticationContext.class);
201 }
202 return authenticationContext;
203 }
204
205 }