View Javadoc

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   * FQCN : com.atlassian.jira.workflow.ExtendedWorkflowManager
35   * @author Kaamelot
36   * @since 3.10.1.30
37   * Description : Extends OSWorkflowManager in order to provide a validateIssue() method called by ExtendedIssueManager 
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  	 * @param _issue Issue about to be Created or Edited
56  	 * @return JIRA Workflow to use for the Issue
57  	 * @throws IllegalArgumentException
58  	 * @throws WorkflowException
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  	/** Performs an Issue Validation based on Workflow validators defined in "Edit Issue" action
72  	 * @param remoteUserName
73  	 * @param fields
74  	 * @throws WorkflowException
75  	 */
76  	public void validateIssue(String remoteUserName, Map fields) throws WorkflowException {
77  		try {
78  			// Determine the workflow for the issue to use
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  			// return ManagerFactory.getIssueManager().getIssueByWorkflow(new Long(wfId));
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 	 * isDeletable
150 	 * @param Issue
151 	 * @return boolean
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) // this should never really be null - but it saves hassle of setting up hundreds of tests with a status
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 					// Is the Meta an Boolean Value
173 					if (attribute.equalsIgnoreCase("true") || attribute.equalsIgnoreCase("false")) {
174 						isDeletable = new Boolean(attribute).booleanValue();
175 					} else { // Is the Meta an Condtion FQCN
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 }