View Javadoc

1   /*
2    * This software was designed and created by Jason Carroll.
3    * Copyright (c) 2002, 2003, 2004 Jason Carroll.
4    * The author can be reached at jcarroll@cowsultants.com
5    * ITracker website: http://www.cowsultants.com
6    * ITracker forums: http://www.cowsultants.com/phpBB/index.php
7    *
8    * This program is free software; you can redistribute it and/or modify
9    * it only under the terms of the GNU General Public License as published by
10   * the Free Software Foundation; either version 2 of the License, or
11   * (at your option) any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   * GNU General Public License for more details.
17   */
18  
19  package org.itracker.web.actions.project;
20  
21  import java.io.IOException;
22  import java.util.Date;
23  import java.util.List;
24  import java.util.Locale;
25  import java.util.Map;
26  import java.util.ResourceBundle;
27  import java.util.Set;
28  
29  import javax.servlet.ServletException;
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  import javax.servlet.http.HttpSession;
33  
34  import org.apache.log4j.Level;
35  import org.apache.log4j.Logger;
36  import org.apache.struts.action.ActionForm;
37  import org.apache.struts.action.ActionForward;
38  import org.apache.struts.action.ActionMapping;
39  import org.apache.struts.action.ActionMessage;
40  import org.apache.struts.action.ActionMessages;
41  import org.apache.struts.validator.ValidatorForm;
42  import org.itracker.core.resources.ITrackerResources;
43  import org.itracker.model.CustomField;
44  import org.itracker.model.Issue;
45  import org.itracker.model.PermissionType;
46  import org.itracker.model.Project;
47  import org.itracker.model.ProjectScript;
48  import org.itracker.model.Status;
49  import org.itracker.model.User;
50  import org.itracker.services.IssueService;
51  import org.itracker.services.NotificationService;
52  import org.itracker.services.exceptions.IssueException;
53  import org.itracker.services.util.CustomFieldUtilities;
54  import org.itracker.services.util.IssueUtilities;
55  import org.itracker.services.util.UserUtilities;
56  import org.itracker.services.util.WorkflowUtilities;
57  import org.itracker.web.actions.base.ItrackerBaseAction;
58  import org.itracker.web.forms.IssueForm;
59  import org.itracker.web.util.Constants;
60  
61  public class EditIssueAction extends ItrackerBaseAction {
62  	private static final Logger log = Logger.getLogger(EditIssueAction.class);
63  
64  	public ActionForward execute(ActionMapping mapping, ActionForm form,
65  			HttpServletRequest request, HttpServletResponse response)
66  	throws ServletException, IOException {
67  		log.info("execute: called");
68  		ActionMessages errors = new ActionMessages();
69  		Date logDate = new Date();
70  		Date startDate = new Date();
71  		logTimeMillies("execute: called", logDate, log, Level.DEBUG);
72  		// TODO: can we make this token optional (configurable) and probably by form, not over the whole app..
73  		if (!isTokenValid(request)) {
74  			log.debug("execute: Invalid request token while editing issue.");
75  
76  			errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
77  			"itracker.web.error.transaction"));
78  			saveErrors(request, errors);
79  			log.info("execute: return to edit-issue");
80  			saveToken(request);
81  			//			return mapping.findForward("error");
82  			return mapping.getInputForward();
83  		}
84  		resetToken(request);
85  
86  
87  		try {
88  			IssueService issueService = getITrackerServices().getIssueService();
89  			if (((IssueForm)form).getId() != null) {
90  				Issue issue = getITrackerServices().getIssueService().getIssue((((IssueForm)form).getId()));			
91  				List<CustomField> projectFields = issue.getProject().getCustomFields();
92  				if (projectFields.size() > 0) {
93  					HttpSession session = request.getSession();
94  					Locale locale = ITrackerResources.getLocale();
95  					if (session != null) {
96  						locale = (Locale) session.getAttribute(Constants.LOCALE_KEY);
97  					}
98  
99  					ResourceBundle bundle = ITrackerResources.getBundle(locale);
100 
101 					for (int i = 0; i < projectFields.size(); i++) {
102 						CustomField customField = projectFields.get(i);
103 						String fieldValue = ((IssueForm)form).getCustomFields().get(String.valueOf(customField.getId()));
104 //						String fieldValue = request.getParameter("customFields("
105 //								+ customField.getId() + ")");
106 						if (fieldValue != null && !fieldValue.equals("")) {
107 							try {
108 								customField.checkAssignable(fieldValue, locale, bundle);
109 							} catch (IssueException ie) {
110 								String label = CustomFieldUtilities.getCustomFieldName(
111 										projectFields.get(i).getId(), locale);
112 								errors.add(ActionMessages.GLOBAL_MESSAGE,
113 										new ActionMessage(ie.getType(), label));
114 							}
115 						} else if (projectFields.get(i).isRequired()) {
116 							String label = CustomFieldUtilities.getCustomFieldName(
117 									projectFields.get(i).getId(), locale);
118 							errors.add(ActionMessages.GLOBAL_MESSAGE,
119 									new ActionMessage(IssueException.TYPE_CF_REQ_FIELD,
120 											label));
121 						}
122 					}
123 				}
124 				if (!errors.isEmpty()) {
125 					saveErrors(request, errors);
126 					log.info("execute: return to edit-issue");
127 					saveToken(request);	
128 					return mapping.getInputForward();
129 				}
130 			}
131 			
132 			logTimeMillies("execute: got issueService", logDate, log, Level.DEBUG);
133 			NotificationService notificationService = getITrackerServices()
134 			.getNotificationService();
135 			HttpSession session = request.getSession(true);
136 			User currUser = (User) session.getAttribute(Constants.USER_KEY);
137 
138 			Map<Integer, Set<PermissionType>> userPermissions = getUserPermissions(session);
139 
140 			Integer currUserId = currUser.getId();
141 			IssueForm issueForm = (IssueForm) form;
142 			int previousStatus = -1;
143 			Issue issue = issueService.getIssue(issueForm.getId());
144 			logTimeMillies("execute: got issue", logDate, log, Level.DEBUG);
145 
146 			if (issue == null) {
147 				errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
148 				"itracker.web.error.invalidissue"));
149 				log.info("execute: invalidissue " + issueForm.getId() + ", Forward: Error");
150 				return mapping.findForward("error");
151 			}
152 
153 			Project project = issue.getProject();
154 			logTimeMillies("execute: got project", logDate, log, Level.DEBUG);
155 			if (project == null) {
156 				errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
157 				"itracker.web.error.invalidproject"));
158 				log.info("execute: Forward: Error");
159 				return mapping.findForward("error");
160 			} else if (project.getStatus() != Status.ACTIVE) {
161 				errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
162 				"itracker.web.error.projectlocked"));
163 				log.info("execute: Forward: Error");
164 				return mapping.findForward("error");
165 			} else if (!IssueUtilities.canEditIssue(issue, currUserId,
166 					userPermissions)) {
167 				log.info("execute: Forward: unauthorized");
168 				return mapping.findForward("unauthorized");
169 			}
170 
171 			List<ProjectScript> scripts = project.getScripts();
172 			logTimeMillies("execute: got scripts", logDate, log, Level.DEBUG);
173 			WorkflowUtilities.processFieldScripts(scripts,
174 					WorkflowUtilities.EVENT_FIELD_ONPRESUBMIT, null, errors,
175 					(ValidatorForm) form);
176 			logTimeMillies("execute: processed field scripts EVENT_FIELD_ONPRESUBMIT", logDate, log, Level.DEBUG);
177 
178 			if (errors.isEmpty()) {
179 				previousStatus = issue.getStatus();
180 				try {
181 					if (UserUtilities.hasPermission(userPermissions, project.getId(),
182 							UserUtilities.PERMISSION_EDIT_FULL)) {
183 						if (log.isDebugEnabled()) {
184 							log.debug("execute: process full, " + issue);
185 						}
186 						issue = EditIssueActionUtil.processFullEdit(issue, project, currUser, userPermissions,
187 								getLocale(request), issueForm, issueService, errors);
188 						logTimeMillies("execute: processed fulledit", logDate, log, Level.DEBUG);
189 					} else {				
190 						if (log.isDebugEnabled()) {
191 							log.debug("execute: process limited, " + issue);
192 						}
193 						issue = EditIssueActionUtil.processLimitedEdit(issue, project, currUser, userPermissions,
194 								getLocale(request), issueForm, issueService, errors);
195 						logTimeMillies("execute: processed limited edit", logDate, log, Level.DEBUG);
196 					}
197 				} catch (Exception e) {
198 					log.warn("execute: failed to update " + issue, e);
199 					errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.other"));
200 					errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(e.getMessage(), false));
201 				}
202 			}
203 
204 			if (errors.isEmpty()) {		
205 				if (log.isDebugEnabled()) {
206 					log.debug("execute: sending notification for issue: " + issue
207 							+ " (HISTORIES: " + issueService.getIssueHistory(issue.getId()) + ")");
208 				}
209 				EditIssueActionUtil.sendNotification(issue.getId(), previousStatus,
210 						getBaseURL(request), notificationService);
211 				logTimeMillies("execute: sent notification", logDate, log, Level.DEBUG);
212 
213 				WorkflowUtilities.processFieldScripts(scripts,
214 						WorkflowUtilities.EVENT_FIELD_ONPOSTSUBMIT, null, errors,
215 						(ValidatorForm) form);
216 				logTimeMillies("execute: processed field scripts EVENT_FIELD_ONPOSTSUBMIT", logDate, log, Level.DEBUG);
217 
218 				return EditIssueActionUtil.getReturnForward(issue, project, issueForm, mapping);
219 			}
220 		} catch (Exception e) {
221 			log.error("execute: Exception processing form data", e);
222 			errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
223 			"itracker.web.error.system"));
224 		} finally {
225 			logTimeMillies("execute: processed", startDate, log, Level.DEBUG);
226 		}
227 
228 		if (!errors.isEmpty()) {
229 			saveMessages(request, errors);
230 			saveErrors(request, errors);
231 			saveToken(request);
232 
233 			return mapping.getInputForward();
234 			//			return null;//mapping.findForward("editissueform");
235 		}
236 
237 		log.info("execute: Forward: Error");
238 		return mapping.findForward("error");
239 	}
240 
241 }