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.admin.configuration;
20  
21  import org.apache.log4j.Logger;
22  import org.apache.struts.action.*;
23  import org.itracker.ProjectException;
24  import org.itracker.UserException;
25  import org.itracker.core.resources.ITrackerResources;
26  import org.itracker.model.*;
27  import org.itracker.model.util.CustomFieldUtilities;
28  import org.itracker.model.util.SystemConfigurationUtilities;
29  import org.itracker.model.util.UserUtilities;
30  import org.itracker.services.ConfigurationService;
31  import org.itracker.services.IssueService;
32  import org.itracker.services.ProjectService;
33  import org.itracker.services.UserService;
34  import org.itracker.PasswordException;
35  import org.itracker.web.actions.base.ItrackerBaseAction;
36  import org.itracker.web.util.Constants;
37  import org.itracker.web.util.ImportExportUtilities;
38  import org.itracker.web.util.LoginUtilities;
39  import org.itracker.web.util.ServletContextUtils;
40  
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.util.ArrayList;
47  import java.util.HashSet;
48  import java.util.List;
49  
50  
51  public class ImportDataProcessAction extends ItrackerBaseAction {
52      private static final Logger log = Logger.getLogger(ImportDataProcessAction.class);
53  
54      private static final class ActionException extends Exception {
55  
56      }
57  
58      public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
59          ActionMessages errors = new ActionMessages();
60  
61  
62          if (!LoginUtilities.hasPermission(UserUtilities.PERMISSION_USER_ADMIN, request, response)) {
63              return mapping.findForward("unauthorized");
64          }
65  
66          try {
67  
68              HttpSession session = request.getSession(false);
69              User importer = LoginUtilities.getCurrentUser(request);
70              if (importer == null || !importer.isSuperUser()) {
71                  return mapping.findForward("unauthorized");
72              }
73  
74              ImportDataModel model = (ImportDataModel) session.getAttribute(Constants.IMPORT_DATA_KEY);
75              if (null == model) {
76                  errors.add(ActionMessages.GLOBAL_MESSAGE,
77                          new ActionMessage("itracker.web.error.system.message", "No model in session.", "Request"));
78              }
79              checkErrors(errors);
80              log.debug("Importing configuration data.");
81              createConfig(model, importer, errors);
82  
83              checkErrors(errors);
84              log.debug("Importing user data.");
85              createUsers(model, importer, errors);
86  
87              checkErrors(errors);
88              log.debug("Importing project data.");
89              createProjects(model, importer, errors);
90  
91              checkErrors(errors);
92              log.debug("Importing issue data.");
93              createIssues(model, importer, errors);
94  
95              checkErrors(errors);
96              log.debug("Import complete.");
97  
98          } catch (ActionException e) {
99              if (errors.isEmpty()) {
100                 log.error("failed with empty errors", e);
101                 errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.system.message", e.getMessage(), "Unexpected"));
102             }
103             return handleErrors(errors, request, mapping);
104         } catch (Exception e) {
105             log.error("Exception while importing data.", e);
106             errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.system.message", e.getMessage(), "Unexpected"));
107             return handleErrors(errors, request, mapping);
108         }
109 
110         errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.importexport.importcomplete"));
111         saveMessages(request, errors);
112         // reset import models
113         request.getSession().removeAttribute(Constants.IMPORT_DATA_KEY);
114         return mapping.findForward("adminindex");
115     }
116 
117     private void checkErrors(ActionMessages errors) throws ActionException{
118         if (!errors.isEmpty()) {
119             throw new ActionException();
120         }
121     }
122 
123     private ActionForward handleErrors(ActionMessages errors, HttpServletRequest request, ActionMapping mapping) {
124 
125         if (!errors.isEmpty()) {
126             saveErrors(request, errors);
127             return mapping.findForward("error");
128         }
129         return null;
130 
131     }
132     private boolean createConfig(ImportDataModel model, User importer, ActionMessages errors) {
133         try {
134             ConfigurationService configurationService = ServletContextUtils.getItrackerServices().getConfigurationService();
135 
136             AbstractEntity[] importData = model.getData();
137             for (int i = 0; i < importData.length; i++) {
138                 if (importData[i] instanceof Configuration && null == model.getExistingModel(i)) {
139                     Configuration configItem = (Configuration) importData[i];
140                     Configuration newConfigItem = configurationService.createConfigurationItem(configItem);
141                     configItem.setId(newConfigItem.getId());
142 
143                     // Now add a new language key
144                     String key = SystemConfigurationUtilities.getLanguageKey(configItem);
145                     configurationService.updateLanguageItem(new Language(ImportExportUtilities.EXPORT_LOCALE_STRING, key, configItem.getName()));
146                     ITrackerResources.clearKeyFromBundles(key, true);
147                 } else if (importData[i] instanceof CustomField && null == model.getExistingModel(i)) {
148                     CustomField customField = (CustomField) importData[i];
149                     CustomField newCustomField = configurationService.createCustomField(customField);
150                     customField.setId(newCustomField.getId());
151 
152                     // Now add new language keys.  One for the field and then add one for for
153                     // each option that exists.
154                     String key = CustomFieldUtilities.getCustomFieldLabelKey(customField.getId());
155                     // TODO, removed name attribute, so it's defaulted to the key
156                     configurationService.updateLanguageItem(new Language(ImportExportUtilities.EXPORT_LOCALE_STRING, key, key));
157                     ITrackerResources.clearKeyFromBundles(key, true);
158                     if (customField.getFieldType() == CustomField.Type.LIST) {
159                         // TODO, removed name attribute, so it's defaulted to the key
160                         for (int j = 0; j < customField.getOptions().size(); j++) {
161                             String optionKey = CustomFieldUtilities.getCustomFieldOptionLabelKey(customField.getId(), customField.getOptions().get(j).getId());
162                             configurationService.updateLanguageItem(new Language(ImportExportUtilities.EXPORT_LOCALE_STRING, optionKey, optionKey));
163                             ITrackerResources.clearKeyFromBundles(optionKey, true);
164                         }
165                     }
166                 }
167             }
168             configurationService.resetConfigurationCache();
169         } catch (RuntimeException e) {
170             log.error("failed to import", e);
171             errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.system.message", e.getMessage()));
172             return false;
173         }
174 
175         return true;
176     }
177 
178     private boolean createUsers(ImportDataModel model, User importer, ActionMessages errors) {
179         try {
180             UserService userService = ServletContextUtils.getItrackerServices().getUserService();
181 
182             AbstractEntity[] importData = model.getData();
183             for (int i = 0; i < importData.length; i++) {
184                 if (importData[i] instanceof User && null == model.getExistingModel(i)) {
185                     User user = (User) importData[i];
186                     user.setRegistrationType(UserUtilities.REGISTRATION_TYPE_IMPORT);
187                     if (model.getCreatePasswords()) {
188                         user.setPassword(UserUtilities.encryptPassword(user.getLogin()));
189                     }
190                     user.setLogin(user.getLogin());
191                     int status = user.getStatus();
192                     User newUser = userService.createUser(user);
193                     user.setId(newUser.getId());
194                     newUser.setStatus(status);
195                     userService.updateUser(newUser);
196                 }
197             }
198         } catch (RuntimeException e) {
199             log.error("failed to import", e);
200             errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.system.message", e.getMessage()));
201             return false;
202         } catch (PasswordException e) {
203             log.error("failed to import", e);
204             errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.system.message", e.getMessage()));
205             return false;
206         } catch (UserException e) {
207             log.error("failed to import", e);
208             errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.system.message", e.getMessage()));
209             return false;
210         }
211 
212         return true;
213     }
214 
215     private boolean createProjects(ImportDataModel model, User importer, ActionMessages errors) {
216         try {
217             ProjectService projectService = ServletContextUtils.getItrackerServices().getProjectService();
218 
219             AbstractEntity[] importData = model.getData();
220             for (int i = 0; i < importData.length; i++) {
221                 if (importData[i] instanceof Project && null == model.getExistingModel(i)) {
222                     final Project project = (Project) importData[i];
223 
224                     Project importProject = new Project(project.getName());
225                     importProject.setStatus(project.getStatus());
226                     importProject.setDescription(project.getDescription());
227 
228                     importProject = projectService.createProject(importProject, importer.getId());
229                     project.setId(importProject.getId());
230 
231                     HashSet<Integer> setOfOwnerIDs = new HashSet<Integer>();
232                     for (int j = 0; j < project.getOwners().size(); j++) {
233                         setOfOwnerIDs.add(project.getOwners().get(j).getId());
234                     }
235                     projectService.setProjectOwners(importProject, setOfOwnerIDs);
236 
237                     HashSet<Integer> setOfFieldIds = new HashSet<Integer>();
238                     for (CustomField field: project.getCustomFields()) {
239                         setOfFieldIds.add(field.getId());
240                     }
241                     projectService.setProjectFields(importProject, setOfFieldIds);
242 
243                     List<Component> components = project.getComponents();
244                     for (Component component: components) {
245                         Component newComponent = projectService.addProjectComponent(importProject.getId(), component);
246                         component.setId(newComponent.getId());
247                     }
248 
249                     List<Version> versions = project.getVersions();
250                     for (Version version:  versions) {
251                         Version newVersion = projectService.addProjectVersion(importProject.getId(), version);
252                         version.setId(newVersion.getId());
253                     }
254                 }
255             }
256         } catch (RuntimeException e) {
257             log.error("createProjects: import failed.", e);
258             errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.system.message", e.getMessage()));
259             return false;
260         }
261 
262         return true;
263     }
264 
265     private boolean createIssues(ImportDataModel model, User importer, ActionMessages errors) {
266         try {
267             IssueService issueService = ServletContextUtils.getItrackerServices().getIssueService();
268 
269             AbstractEntity[] importData = model.getData();
270             for (int i = 0; i < importData.length; i++) {
271                 if (importData[i] instanceof Issue && null == model.getExistingModel(i)) {
272 
273                     Issue issue = (Issue) importData[i];
274                     if (issue.getProject().getStatus() != Status.ACTIVE) {
275                         log.warn("createIssues: could not create issue for NON-Active project: " + issue);
276                         continue;
277                     }
278 
279                     final List<IssueHistory> history = issue.getHistory();
280                     issue.setHistory(new ArrayList<IssueHistory>());
281 
282                     List<Component> componentsList = issue.getComponents();
283                     issue.setComponents(new ArrayList<Component>());
284 
285                     List<Version> versionsList = issue.getVersions();
286                     issue.setVersions(new ArrayList<Version>());
287 
288                     List<IssueAttachment> attachments = issue.getAttachments();
289                     issue.setAttachments(new ArrayList<IssueAttachment>());
290 
291 
292                     Issue newIssue = issueService.createIssue(issue,
293                             issue.getProject().getId(), issue.getCreator().getId(), importer.getId());
294                     issue.setId(newIssue.getId());
295 
296                     // Assign the issue
297                     if (issue.getOwner() != null) {
298                         issueService.assignIssue(issue.getId(), issue.getOwner().getId(), importer.getId());
299                     }
300 
301                     // Now set Issue Custom Fields
302                     // TODO:?
303                     List<IssueField> fields = issue.getFields();
304                     if (!fields.isEmpty()) {
305                         for (IssueField f : fields) {
306                             f.setIssue(issue);
307                         }
308                         issueService.setIssueFields(issue.getId(), issue.getFields());
309                     }
310 
311 
312                     // Now add all the issue history
313                     for (IssueHistory h: history) {
314                         h.setIssue(newIssue);
315                         issueService.addIssueHistory(h);
316                      // needed?   issueService.updateIssue(newIssue, importer.getId());
317                     }
318 
319 
320                     // Now add components and versions
321                     HashSet<Integer> components = new HashSet<Integer>();
322                     for (Component c: componentsList) {
323                         components.add(c.getId());
324                     }
325                     if (!components.isEmpty()) {
326                         issueService.setIssueComponents(newIssue.getId(), components, importer.getId());
327                     }
328 
329                     HashSet<Integer> versions = new HashSet<Integer>();
330                     for (Version v: versionsList) {
331                         versions.add(v.getId());
332                     }
333                     if (!versions.isEmpty()) {
334                         issueService.setIssueVersions(newIssue.getId(), versions, importer.getId());
335                     }
336 
337 
338                     // Now add any attachments
339                     for (IssueAttachment a : attachments) {
340                         a.setIssue(newIssue);
341                         issueService.addIssueAttachment(a, null);
342                     }
343                 }
344             }
345         } catch (ProjectException e) {
346             log.error("createIssues: import failed.", e);
347             errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.system.message", e.getMessage()));
348             return false;
349         }
350 
351         return true;
352     }
353 
354 }
355