1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.itracker.web.actions.admin.configuration;
20
21 import org.apache.commons.beanutils.PropertyUtils;
22 import org.apache.log4j.Logger;
23 import org.apache.struts.action.*;
24 import org.apache.struts.upload.FormFile;
25 import org.itracker.ImportExportException;
26 import org.itracker.core.resources.ITrackerResources;
27 import org.itracker.model.*;
28 import org.itracker.model.util.SystemConfigurationUtilities;
29 import org.itracker.model.util.UserUtilities;
30 import org.itracker.persistence.dao.NoSuchEntityException;
31 import org.itracker.services.ConfigurationService;
32 import org.itracker.services.ProjectService;
33 import org.itracker.services.UserService;
34 import org.itracker.web.actions.base.ItrackerBaseAction;
35 import org.itracker.web.util.Constants;
36 import org.itracker.web.util.ImportExportUtilities;
37 import org.itracker.web.util.LoginUtilities;
38 import org.itracker.web.util.ServletContextUtils;
39
40 import javax.naming.InitialContext;
41 import javax.servlet.ServletException;
42 import javax.servlet.http.HttpServletRequest;
43 import javax.servlet.http.HttpServletResponse;
44 import javax.servlet.http.HttpSession;
45 import java.io.IOException;
46 import java.io.InputStreamReader;
47 import java.util.List;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public class ImportDataVerifyAction extends ItrackerBaseAction {
64 private static final Logger log = Logger.getLogger(ImportDataVerifyAction.class);
65
66 private static final int UPDATE_STATUS = 1;
67 private static final int UPDATE_SEVERITY = 2;
68 private static final int UPDATE_RESOLUTION = 3;
69
70 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
71 ActionMessages errors = new ActionMessages();
72
73
74 if (!LoginUtilities.hasPermission(PermissionType.USER_ADMIN, request, response)) {
75 return mapping.findForward("unauthorized");
76 }
77
78 try {
79 FormFile file = (FormFile) PropertyUtils.getSimpleProperty(form, "importFile");
80 ImportDataModel model = new ImportDataModel();
81 AbstractEntity[] importData = ImportExportUtilities.importIssues(new InputStreamReader(file.getInputStream()));
82 AbstractEntity[] existingModel = new AbstractEntity[importData.length];
83
84 model.setReuseUsers((Boolean) PropertyUtils.getSimpleProperty(form, "optionreuseusers"));
85 model.setReuseProjects((Boolean) PropertyUtils.getSimpleProperty(form, "optionreuseprojects"));
86 model.setReuseConfig((Boolean) PropertyUtils.getSimpleProperty(form, "optionreuseconfig"));
87 model.setCreatePasswords((Boolean) PropertyUtils.getSimpleProperty(form, "optioncreatepasswords"));
88 model.setData(importData, existingModel);
89
90 InitialContext ic = new InitialContext();
91 checkConfig(model, ic);
92 log.debug(model.toString());
93 checkUsers(model, ic);
94 log.debug(model.toString());
95 checkProjects(model, ic);
96 log.debug(model.toString());
97 checkIssues(model, ic);
98 log.debug(model.toString());
99
100 HttpSession session = request.getSession(true);
101 session.setAttribute(Constants.IMPORT_DATA_KEY, model);
102 } catch (ImportExportException iee) {
103 if (iee.getType() == ImportExportException.TYPE_INVALID_LOGINS) {
104 log.error("Invalid logins found while verifying import data.");
105 errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.importexport.invalidlogins", iee.getMessage()));
106 } else if (iee.getType() == ImportExportException.TYPE_INVALID_STATUS) {
107 log.error("Invalid status found while verifying import data.");
108 errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.importexport.invalidstatus", iee.getMessage()));
109 } else {
110 log.error("Exception while verifying import data.", iee);
111 errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.system"));
112 }
113 } catch (Exception e) {
114 log.error("Exception while verifying import data.", e);
115 errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.system"));
116 }
117
118 if (!errors.isEmpty()) {
119 saveErrors(request, errors);
120 return mapping.getInputForward();
121 }
122
123 return mapping.findForward("importdataverify");
124 }
125
126 private void checkConfig(ImportDataModel model, InitialContext ic) throws ImportExportException {
127 try {
128 int maxSeverityValue = 1;
129 int maxResolutionValue = 1;
130
131 ConfigurationService configurationService = getITrackerServices().getConfigurationService();
132
133 List<Configuration> statuses = configurationService.getConfigurationItemsByType(Configuration.Type.status, ImportExportUtilities.EXPORT_LOCALE);
134 List<Configuration> severities = configurationService.getConfigurationItemsByType(Configuration.Type.severity, ImportExportUtilities.EXPORT_LOCALE);
135 List<Configuration> resolutions = configurationService.getConfigurationItemsByType(Configuration.Type.resolution, ImportExportUtilities.EXPORT_LOCALE);
136 List<CustomField> fields = configurationService.getCustomFields();
137
138 for (int i = 0; i < severities.size(); i++) {
139 maxSeverityValue = Math.max(maxSeverityValue, Integer.parseInt(severities.get(i).getValue()));
140 }
141 for (int i = 0; i < resolutions.size(); i++) {
142 maxResolutionValue = Math.max(maxResolutionValue, Integer.parseInt(resolutions.get(i).getValue()));
143 }
144
145 AbstractEntity[] importData = model.getData();
146 for (int i = 0; i < importData.length; i++) {
147 if (importData[i] instanceof Configuration) {
148
149
150
151
152
153 Configuration configItem = (Configuration) importData[i];
154 if (configItem.getType() == Configuration.Type.status) {
155 boolean found = false;
156 for (int j = 0; j < statuses.size(); j++) {
157 if (model.getReuseConfig() && statuses.get(j).getName().equalsIgnoreCase(configItem.getName())) {
158
159 updateIssues(importData, UPDATE_STATUS, configItem.getValue(), statuses.get(j).getValue());
160 model.setExistingModel(i, configItem);
161 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_STATUSES, ImportExportUtilities.IMPORT_STAT_REUSED);
162 found = true;
163 break;
164 } else if (statuses.get(j).getValue().equalsIgnoreCase(configItem.getValue())) {
165
166 throw new ImportExportException(configItem.getValue(), ImportExportException.TYPE_INVALID_STATUS);
167 }
168 }
169 if (!found) {
170 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_STATUSES, ImportExportUtilities.IMPORT_STAT_NEW);
171 }
172 } else if (configItem.getType() == Configuration.Type.severity) {
173 boolean found = false;
174 if (model.getReuseConfig()) {
175 for (int j = 0; j < severities.size(); j++) {
176 if (severities.get(j).getName().equalsIgnoreCase(configItem.getName())) {
177
178 updateIssues(importData, UPDATE_SEVERITY, configItem.getValue(), severities.get(j).getValue());
179 model.setExistingModel(i, configItem);
180 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_SEVERITIES, ImportExportUtilities.IMPORT_STAT_REUSED);
181 found = true;
182 break;
183 }
184 }
185 }
186 if (!found) {
187 updateIssues(importData, UPDATE_SEVERITY, configItem.getValue(), Integer.toString(++maxSeverityValue));
188 configItem.setValue(Integer.toString(maxSeverityValue));
189 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_SEVERITIES, ImportExportUtilities.IMPORT_STAT_NEW);
190 }
191 } else if (configItem.getType() == Configuration.Type.resolution) {
192 boolean found = false;
193 if (model.getReuseConfig()) {
194 for (int j = 0; j < resolutions.size(); j++) {
195 if (resolutions.get(j).getName().equalsIgnoreCase(configItem.getName())) {
196
197 updateIssues(importData, UPDATE_RESOLUTION, configItem.getValue(), resolutions.get(j).getValue());
198 model.setExistingModel(i, configItem);
199 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_RESOLUTIONS, ImportExportUtilities.IMPORT_STAT_REUSED);
200 found = true;
201 break;
202 }
203 }
204 }
205 if (!found) {
206 updateIssues(importData, UPDATE_RESOLUTION, configItem.getValue(), Integer.toString(++maxResolutionValue));
207 configItem.setValue(Integer.toString(maxResolutionValue));
208 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_RESOLUTIONS, ImportExportUtilities.IMPORT_STAT_NEW);
209 }
210 }
211 } else if (importData[i] instanceof CustomField) {
212 boolean found = false;
213 CustomField field = (CustomField) importData[i];
214 if (model.getReuseFields()) {
215 for (int j = 0; j < fields.size(); j++) {
216 if (fields.get(j).getFieldType() == field.getFieldType() ) {
217
218
219 field.setId(fields.get(j).getId());
220 model.setExistingModel(i, field);
221 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_FIELDS, ImportExportUtilities.IMPORT_STAT_REUSED);
222 found = true;
223 break;
224 }
225 }
226 }
227 if (!found) {
228 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_FIELDS, ImportExportUtilities.IMPORT_STAT_NEW);
229 }
230 }
231 }
232 } catch (ImportExportException iee) {
233 throw iee;
234 } catch (Exception e) {
235 log.error("Error verifiying import data.", e);
236 throw new ImportExportException(e.getMessage());
237 }
238 }
239
240 private void checkUsers(ImportDataModel model, InitialContext ic) throws ImportExportException {
241 String invalidLogins = null;
242
243 try {
244 UserService userService = getITrackerServices().getUserService();
245
246 AbstractEntity[] importData = model.getData();
247
248 for (int i = 0; i < importData.length; i++) {
249 if (importData[i] instanceof User) {
250 User user = (User) importData[i];
251 User existingUser;
252 try {
253 existingUser = userService.getUserByLogin(user.getLogin());
254 } catch (NoSuchEntityException e) {
255 existingUser = null;
256 }
257 if (existingUser != null) {
258 if (model.getReuseUsers()) {
259 user.setId(existingUser.getId());
260 model.setExistingModel(i, existingUser);
261 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_USERS, ImportExportUtilities.IMPORT_STAT_REUSED);
262 log.debug("Reusing existing user " + user.getLogin() + "(" + user.getId() + ") during import.");
263 } else {
264 log.debug("Existing user " + existingUser.getLogin() + "(" + existingUser.getId() + ") during import. Adding to invalid login list.");
265 invalidLogins = (invalidLogins == null ?
266 existingUser.getLogin() :
267 new StringBuffer(invalidLogins).append(", ").append(existingUser.getLogin()).toString());
268 }
269 } else {
270 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_USERS, ImportExportUtilities.IMPORT_STAT_NEW);
271 }
272 }
273 }
274 } catch (Exception e) {
275 log.error("Error verifying import data.", e);
276 throw new ImportExportException(e.getMessage());
277 }
278
279 if (invalidLogins != null) {
280 throw new ImportExportException(invalidLogins, ImportExportException.TYPE_INVALID_LOGINS);
281 }
282 }
283
284 private void checkProjects(ImportDataModel model, InitialContext ic) throws ImportExportException {
285 try {
286 ProjectService projectService = ServletContextUtils.getItrackerServices().getProjectService();
287
288 List<Project> existingProjects = projectService.getAllProjects();
289
290 AbstractEntity[] importData = model.getData();
291
292 for (int i = 0; i < importData.length; i++) {
293 if (importData[i] instanceof Project) {
294 if (!model.getReuseProjects()) {
295 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_PROJECTS, ImportExportUtilities.IMPORT_STAT_NEW);
296 continue;
297 }
298
299 Project project = (Project) importData[i];
300 for (int j = 0; j < existingProjects.size(); j++) {
301 log.debug("Project Name: " + project.getName() + " Existing Project: " + existingProjects.get(j).getName());
302 log.debug("Project Name: " + ITrackerResources.escapeUnicodeString(project.getName(), false) + " Existing Project: " + ITrackerResources.escapeUnicodeString(existingProjects.get(j).getName(), false));
303 if (project.getName() != null && project.getName().equalsIgnoreCase(existingProjects.get(j).getName())) {
304 project.setId(existingProjects.get(j).getId());
305 model.setExistingModel(i, project);
306 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_PROJECTS, ImportExportUtilities.IMPORT_STAT_REUSED);
307
308 log.debug("Reusing existing project " + project.getName() + "(" + project.getId() + ") during import.");
309 break;
310 }
311 }
312 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_PROJECTS, ImportExportUtilities.IMPORT_STAT_NEW);
313
314 }
315 }
316 } catch (Exception e) {
317 log.error("Error verifiying import data.", e);
318 throw new ImportExportException(e.getMessage());
319 }
320 }
321
322 private void checkIssues(ImportDataModel model, InitialContext ic) throws ImportExportException {
323 AbstractEntity[] importData = model.getData();
324
325 for (int i = 0; i < importData.length; i++) {
326 if (importData[i] instanceof Issue) {
327 model.addVerifyStatistic(ImportExportUtilities.IMPORT_STAT_ISSUES, ImportExportUtilities.IMPORT_STAT_NEW);
328 }
329 }
330 }
331
332 private void updateIssues(AbstractEntity[] models, int updateType, String currentValue, String newValue) throws ImportExportException {
333 if (models == null || currentValue == null || newValue == null) {
334 return;
335 }
336
337 try {
338 for (int i = 0; i < models.length; i++) {
339 if (models[i] instanceof Issue) {
340 Issue issue = (Issue) models[i];
341 if (updateType == UPDATE_STATUS && issue.getStatus() == Integer.parseInt(currentValue)) {
342 issue.setStatus(Integer.parseInt(newValue));
343 } else if (updateType == UPDATE_SEVERITY && issue.getSeverity() == Integer.parseInt(currentValue)) {
344 issue.setSeverity(Integer.parseInt(newValue));
345 } else if (updateType == UPDATE_RESOLUTION && currentValue.equalsIgnoreCase(issue.getResolution())) {
346 issue.setResolution(newValue);
347 }
348 }
349 }
350 } catch (Exception e) {
351 log.debug("Unable to update configuration data in issues.", e);
352 throw new ImportExportException("Unable to update configuration data in issues: " + e.getMessage());
353 }
354 }
355 }
356