@Override
  public WhitelistUpdateValidationResult validateUpdateRules(
      final JiraServiceContext context, final List<String> rules, final boolean disabled) {
    notNull("context", context);
    notNull("rules", rules);

    if (checkInvalidPermissions(context)) {
      return new WhitelistUpdateValidationResult(context.getErrorCollection());
    }

    for (String rule : rules) {
      if (rule.startsWith(REGEX_PREFIX)) {
        try {
          Pattern.compile(rule.substring(REGEX_PREFIX.length()));
        } catch (PatternSyntaxException e) {
          final I18nHelper i18n = beanFactory.getInstance(context.getLoggedInUser());
          context
              .getErrorCollection()
              .addErrorMessage(i18n.getText("whitelist.admin.errors.bad.pattern", e.getMessage()));
        }
      }
    }

    return new WhitelistUpdateValidationResult(context.getErrorCollection(), rules, disabled);
  }
 public MessageSet validate(
     final User searcher,
     final FunctionOperand functionOperand,
     final TerminalClause terminalClause) {
   final MessageSet messageSet;
   I18nHelper i18n = getI18n();
   if (functionOperand.getArgs().size() == 0 && searcher == null) {
     messageSet = new MessageSetImpl();
     messageSet.addErrorMessage(
         i18n.getText("jira.jql.function.anonymous.disallowed", getFunctionName()));
   } else {
     MessageSet messages = validateNumberOfArgs(functionOperand, i18n);
     if (!messages.hasAnyErrors()) {
       if (functionOperand.getArgs().size() == 1) {
         final String username = functionOperand.getArgs().get(0);
         if (userUtil.getUserObject(username) == null) {
           messages.addErrorMessage(
               i18n.getText(getUserNotFoundMessageKey(), functionOperand.getName(), username));
         }
       }
     }
     return messages;
   }
   return messageSet;
 }
Пример #3
0
 /**
  * validate the field value
  *
  * @param operationContext OperationContext
  * @param errorCollectionToAddTo ErrorCollection
  * @param i18n I18nHelper
  * @param issue Issue
  * @param fieldScreenRenderLayoutItem FieldScreenRenderLayoutItem
  */
 public void validateParams(
     OperationContext operationContext,
     ErrorCollection errorCollectionToAddTo,
     I18nHelper i18n,
     Issue issue,
     FieldScreenRenderLayoutItem fieldScreenRenderLayoutItem) {
   Map fieldValuesHolder = operationContext.getFieldValuesHolder();
   String summary = (String) getValueFromParams(fieldValuesHolder);
   if (summary == null) {
     errorCollectionToAddTo.addError(getId(), i18n.getText("createissue.error.specify.a.summary"));
     return;
   }
   // JRADEV-1867 User can create summary with "  "
   summary = summary.trim();
   if (!TextUtils.stringSet(summary)) {
     errorCollectionToAddTo.addError(getId(), i18n.getText("createissue.error.specify.a.summary"));
   }
   if (summary.contains("\n") || summary.contains("\r")) {
     errorCollectionToAddTo.addError(getId(), i18n.getText("createissue.invalidsummary.newlines"));
   }
   if (summary.length() > MAX_LEN) {
     errorCollectionToAddTo.addError(
         getId(), i18n.getText("createissue.error.summary.less.than", MAX_LEN.toString()));
   }
 }
 void validateCustomFieldPluginVersions(
     final BackupProject backupProject,
     final Collection backupPluginVersions,
     final MessageSet messageSet,
     final I18nHelper i18n) {
   for (final Iterator iterator = backupProject.getCustomFields().iterator();
       iterator.hasNext(); ) {
     final ExternalCustomFieldConfiguration customFieldConfiguration =
         (ExternalCustomFieldConfiguration) iterator.next();
     String key = customFieldConfiguration.getCustomField().getTypeKey();
     // The key is the plugin container key, a colon, then the module key (e.g.
     // com.atlassian.jira.plugin.system.customfieldtypes:textarea)
     // We just get the plugin container key, as this is where the version exists.
     final int index = key.indexOf(":");
     // This should never happen unless there was a bad plugin module installed in the backup data,
     // if this is
     // the case then we just want to use the key as specified and let the error propagate to the
     // user screen
     if (index != -1) {
       key = key.substring(0, index);
     }
     // Does this plugin exist in the current JIRA instance
     final Plugin plugin = pluginAccessor.getPlugin(key);
     if (plugin != null) {
       final String currentPluginVersion = plugin.getPluginInformation().getVersion();
       String backupVersion = null;
       for (final Iterator iterator1 = backupPluginVersions.iterator(); iterator1.hasNext(); ) {
         final PluginVersion pluginVersion = (PluginVersion) iterator1.next();
         if (pluginVersion.getKey().equals(key)) {
           backupVersion = pluginVersion.getVersion();
           break;
         }
       }
       if (!currentPluginVersion.equals(backupVersion)) {
         final String customFieldName = customFieldConfiguration.getCustomField().getName();
         if (backupVersion == null) {
           messageSet.addErrorMessage(
               i18n.getText(
                   "admin.error.project.import.plugin.wrong.version.null.backup",
                   backupProject.getProject().getName(),
                   customFieldName,
                   customFieldConfiguration.getCustomField().getTypeKey(),
                   currentPluginVersion));
         } else {
           messageSet.addErrorMessage(
               i18n.getText(
                   "admin.error.project.import.plugin.wrong.version",
                   backupProject.getProject().getName(),
                   customFieldName,
                   customFieldConfiguration.getCustomField().getTypeKey(),
                   currentPluginVersion,
                   backupVersion));
         }
       }
     }
   }
 }
 boolean checkInvalidPermissions(final JiraServiceContext context) {
   if (!permissionManager.hasPermission(Permissions.SYSTEM_ADMIN, context.getLoggedInUser())) {
     final I18nHelper i18n = beanFactory.getInstance(context.getLoggedInUser());
     context
         .getErrorCollection()
         .addErrorMessage(i18n.getText("whitelist.service.permission.error"));
     return true;
   }
   return false;
 }
  public Map getValues(Map userParams) {
    User u = (User) userParams.get("User");
    I18nHelper i18nHelper = new I18nBean(u);

    return EasyMap.build(
        FILTER_ALL_ISSUES,
        i18nHelper.getText("timetracking.limit.all"),
        FILTER_INCOMPLETE_ISSUES,
        i18nHelper.getText("timetracking.limit.incomplete.only"));
  }
  @Test
  public void testExecuteBuildNumberTooOldInXml() throws Exception {
    expect(mockBeanFactory.getInstance(currentUser)).andReturn(mockI18nHelper).anyTimes();
    expect(mockI18nHelper.getText("data.import.parse.xml")).andReturn("Parsing XML");
    expect(
            mockI18nHelper.getText(
                EasyMock.eq("data.import.parse.progress"),
                EasyMock.<String>anyObject(),
                EasyMock.<String>anyObject()))
        .andReturn("Parsing progress");

    // called during validation!
    expect(mockPermissionManager.hasPermission(Permissions.SYSTEM_ADMIN, currentUser))
        .andReturn(true);

    // This is called during the first parse of the XML file.  At this stage nothing should have
    // been created yet!
    final MockGenericValue mockGv = new MockGenericValue("someentity");
    expect(mockOfBizDelegator.makeValue(EasyMock.<String>anyObject())).andReturn(mockGv).anyTimes();
    expect(mockAttachmentPathManager.getDefaultAttachmentPath())
        .andReturn(directories.get(0).getAbsolutePath())
        .anyTimes();
    expect(mockIndexPathManager.getDefaultIndexRootPath())
        .andReturn(directories.get(1).getAbsolutePath())
        .anyTimes();
    expect(
            mockLicenseStringFactory.create(
                EasyMock.<String>anyObject(), EasyMock.<String>anyObject()))
        .andStubReturn("");

    // after the first parse check the build number.
    expect(mockBuildUtilsInfo.getCurrentBuildNumber()).andStubReturn("400");
    expect(mockBuildUtilsInfo.getMinimumUpgradableBuildNumber()).andStubReturn("18");

    // after the first parse we also verify the license is good.
    expect(
            mockJiraLicenseService.validate(
                EasyMock.<I18nHelper>anyObject(), EasyMock.<String>anyObject()))
        .andStubReturn(mockValidationResult);
    expect(mockValidationResult.getLicenseVersion()).andStubReturn(2);
    expect(mockValidationResult.getErrorCollection()).andStubReturn(new SimpleErrorCollection());

    expect(
            mockExternalLinkUtil.getProperty(
                "external.link.jira.confluence.upgrade.guide.for.old.versions"))
        .andReturn("http://www.atlassian.com");

    expect(mockI18nHelper.getText("data.import.error.xml.too.old", "http://www.atlassian.com"))
        .andReturn("Data is too old visit http://www.atlassian.com/");

    final String filePath = getDataFilePath("jira-export-test-too-old.xml");
    final DataImportParams params = new DataImportParams.Builder(filePath).build();
    executeTest(params, false, DataImportService.ImportError.NONE);
  }
  @Override
  public void validateFromParams(
      CustomFieldParams cfParams, ErrorCollection errorCollection, FieldConfig fieldConfig) {
    @SuppressWarnings("unchecked")
    final Collection<String> params = cfParams.getAllValues();
    CustomField cf = fieldConfig.getCustomField();
    JiraAuthenticationContext authCtx =
        ComponentManager.getInstance().getJiraAuthenticationContext();
    I18nHelper i18n = authCtx.getI18nHelper();
    UserProjectHistoryManager userProjectHistoryManager =
        ComponentManager.getComponentInstanceOfType(UserProjectHistoryManager.class);
    Project currentProject =
        userProjectHistoryManager.getCurrentProject(Permissions.BROWSE, authCtx.getLoggedInUser());

    boolean isAutocompleteView;
    if (cf.isAllProjects()) {
      isAutocompleteView =
          qfMgr.isAutocompleteView(cf.getIdAsLong(), Consts.PROJECT_ID_FOR_GLOBAL_CF);
    } else {
      isAutocompleteView = qfMgr.isAutocompleteView(cf.getIdAsLong(), currentProject.getId());
    }

    if (isAutocompleteView) {
      if ((params == null) || params.isEmpty()) {
        boolean addNull;
        if (cf.isAllProjects()) {
          addNull = qfMgr.getAddNull(cf.getIdAsLong(), Consts.PROJECT_ID_FOR_GLOBAL_CF);
        } else {
          addNull = qfMgr.getAddNull(cf.getIdAsLong(), currentProject.getId());
        }

        if (!addNull) {
          errorCollection.addError(
              fieldConfig.getFieldId(), i18n.getText("queryfields.error.isnotnull"));
        }
      } else {
        if (params.size() > 1) {
          errorCollection.addError(
              fieldConfig.getFieldId(), i18n.getText("queryfields.error.invalid.params"));
        } else {
          for (String param : params) {
            Issue issue = issueMgr.getIssueObject(param);
            if (issue == null) {
              errorCollection.addError(
                  fieldConfig.getFieldId(), i18n.getText("queryfields.error.notissue", param));
            }
          }
        }
      }
    }
  }
  @Test
  public void testVersion1License() throws Exception {
    expect(mockBeanFactory.getInstance(currentUser)).andReturn(mockI18nHelper).anyTimes();
    expect(mockI18nHelper.getText("data.import.parse.xml")).andReturn("Parsing XML");
    expect(
            mockI18nHelper.getText(
                EasyMock.eq("data.import.parse.progress"),
                EasyMock.<String>anyObject(),
                EasyMock.<String>anyObject()))
        .andReturn("Parsing progress");

    // called during validation!
    expect(mockPermissionManager.hasPermission(Permissions.SYSTEM_ADMIN, currentUser))
        .andReturn(true);
    expect(mockJiraLicenseService.validate(mockI18nHelper, "version1license"))
        .andReturn(mockValidationResult);
    expect(mockValidationResult.getLicenseVersion()).andReturn(1);
    expect(mockValidationResult.getErrorCollection()).andReturn(new SimpleErrorCollection());

    // This is called during the first parse of the XML file.  At this stage nothing should have
    // been created yet!
    final MockGenericValue mockGv = new MockGenericValue("someentity");
    expect(mockOfBizDelegator.makeValue(EasyMock.<String>anyObject())).andReturn(mockGv).anyTimes();
    expect(mockAttachmentPathManager.getDefaultAttachmentPath())
        .andReturn(directories.get(0).getAbsolutePath())
        .anyTimes();
    expect(mockIndexPathManager.getDefaultIndexRootPath())
        .andReturn(directories.get(1).getAbsolutePath())
        .anyTimes();
    expect(
            mockLicenseStringFactory.create(
                EasyMock.<String>anyObject(), EasyMock.<String>anyObject()))
        .andStubReturn("");

    // after the first parse check the build number.
    expect(mockBuildUtilsInfo.getCurrentBuildNumber()).andStubReturn("99999999");
    expect(mockBuildUtilsInfo.getMinimumUpgradableBuildNumber()).andStubReturn("0");

    // after the first parse we also verify the license is good.
    expect(
            mockJiraLicenseService.validate(
                EasyMock.<I18nHelper>anyObject(), EasyMock.<String>anyObject()))
        .andStubReturn(mockValidationResult);
    expect(mockValidationResult.getLicenseVersion()).andStubReturn(2);
    expect(mockValidationResult.getErrorCollection()).andStubReturn(new SimpleErrorCollection());

    final String filePath = getDataFilePath("jira-export-test.xml");
    final DataImportParams params =
        new DataImportParams.Builder(filePath).setLicenseString("version1license").build();
    executeTest(params, false, DataImportService.ImportError.V1_LICENSE_EXCEPTION);
  }
  @Test
  public void testUnsafeAOFileNonExistent() throws Exception {
    expect(mockBeanFactory.getInstance(currentUser)).andReturn(mockI18nHelper).anyTimes();
    expect(mockPermissionManager.hasPermission(Permissions.SYSTEM_ADMIN, currentUser))
        .andReturn(true);
    expect(
            mockI18nHelper.getText(
                EasyMock.eq("admin.errors.could.not.find.file"), EasyMock.<String>anyObject()))
        .andReturn("File does not exist.");

    final File file = File.createTempFile("testUnsafeAOFileNonExistent", "txt");
    file.deleteOnExit();

    try {
      final DataImportParams params =
          new DataImportParams.Builder(null)
              .setUnsafeJiraBackup(file)
              .setUnsafeAOBackup(
                  new File("I.really.really.don't.exist.and.if.i.did.it.would.be.very.unlucky"))
              .build();
      executeTest(params, false, DataImportService.ImportError.NONE);
      fail("Calling doImport with invalid validation result should have thrown an exception!");
    } catch (IllegalStateException e) {
      // yay
    } finally {
      file.delete();
    }
  }
  @Test
  public void testSetupImportWhenAlreadySetup() throws Exception {
    expect(mockBeanFactory.getInstance(currentUser)).andReturn(mockI18nHelper).anyTimes();
    mockProperties.setString(APKeys.JIRA_SETUP, "true");
    expect(mockI18nHelper.getText("admin.errors.import.already.setup"))
        .andReturn("Already setup. Should do xml restore");
    expect(mockI18nHelper.getText("admin.errors.must.enter.xml2")).andReturn("Must provide file");

    try {
      final DataImportParams params = new DataImportParams.Builder("").setupImport().build();
      executeTest(params, false, DataImportService.ImportError.NONE);
      fail("Calling doImport with invalid validation result should have thrown an exception!");
    } catch (IllegalStateException e) {
      // yay
    }
  }
  public void testHeadingMarkupForNoResolution() {
    expect(i18n.getText("common.resolution.unresolved")).andReturn("nouser");

    replay(i18n);

    String s =
        ObjectToFieldValueMapper.transform("resolution", null, FULL_URL, transformer).getHtml();

    assertEquals("<a href='" + FULL_URL + "'>nouser</a>", s);
  }
  public void testHeadingMarkupForNoPriority() {
    expect(i18n.getText("gadget.filterstats.priority.nopriority")).andReturn("nopriority");

    replay(i18n);

    String s =
        ObjectToFieldValueMapper.transform("priorities", null, FULL_URL, transformer).getHtml();

    assertEquals("<a href='" + FULL_URL + "'>nopriority</a>", s);
  }
  public void testHeadingMarkupForNoComponent() {
    expect(i18n.getText("gadget.filterstats.component.nocomponent")).andReturn("nocomps");

    replay(i18n);

    String s =
        ObjectToFieldValueMapper.transform("components", null, FULL_URL, transformer).getHtml();

    assertEquals("<a href='" + FULL_URL + "'>nocomps</a>", s);
  }
  public void testHeadingMarkupForNoAssignee() {
    expect(i18n.getText("gadget.filterstats.assignee.unassigned")).andReturn("nouser");

    replay(i18n);

    String s =
        ObjectToFieldValueMapper.transform("assignees", null, FULL_URL, transformer).getHtml();

    assertEquals("<a href='" + FULL_URL + "'>nouser</a>", s);
  }
  public void testHeadingMarkupForNoValueCustomFields() {
    expect(i18n.getText("common.words.none")).andReturn("none");

    replay(i18n);

    final StatsMarkup statsMarkup =
        ObjectToFieldValueMapper.transform("customfield_nick", null, FULL_URL, transformer);

    assertEquals("<a href='" + FULL_URL + "'>none</a>", statsMarkup.getHtml());
  }
  public void testHeadingMarkupForNoFixFor() {
    Version version = null;
    expect(i18n.getText("gadget.filterstats.fixfor.unscheduled")).andReturn("none");

    replay(i18n);

    final StatsMarkup statsMarkup =
        ObjectToFieldValueMapper.transform("fixfor", version, FULL_URL, transformer);

    String s = statsMarkup.getHtml();
    assertEquals("<a href='" + FULL_URL + "'>none</a>", s);
  }
  public ErrorCollection validateDetails(HandlerDetailsModel details) {
    final SimpleErrorCollection errorCollection = new SimpleErrorCollection();
    final I18nHelper i18nHelper = authenticationContext.getI18nHelper();

    if (details.isCreateusers()) {
      // Check that the default reporter is NOT configured
      // As if it is configured and creating users is set to true,
      // it is ambiguous whether to create a new user or use the default reporter
      final boolean extUserMgmt = !userManager.hasWritableDirectory();
      if (StringUtils.isNotBlank(details.getReporterusername())) {
        if (extUserMgmt) {
          errorCollection.addError(
              "createusers", i18nHelper.getText("jmp.editHandlerDetails.error.external.user"));
        } else {
          errorCollection.addError(
              "reporterusername",
              i18nHelper.getText("jmp.editHandlerDetails.create.users.is.enabled"));
        }
      } else if (extUserMgmt) {
        errorCollection.addError(
            "createusers", i18nHelper.getText("jmp.editHandlerDetails.cant.create.users"));
      }
    }

    if (StringUtils.isNotBlank(details.getReporterusername())
        && !userUtil.userExists(details.getReporterusername())) {
      errorCollection.addError(
          "reporterusername", i18nHelper.getText("admin.errors.users.user.does.not.exist"));
    }

    if (StringUtils.isNotBlank(details.getCatchemail())
        && !TextUtils.verifyEmail(TextUtils.noNull(details.getCatchemail()).trim())) {
      errorCollection.addError("catchemail", i18nHelper.getText("admin.errors.invalid.email"));
    }

    if ("forward".equals(details.getBulk()) && StringUtils.isBlank(details.getForwardEmail())) {
      errorCollection.addError(
          "bulk", i18nHelper.getText("jmp.editHandlerDetails.forwardEmail.is.not.set"));
    }

    if (StringUtils.isNotBlank(details.getForwardEmail())
        && !TextUtils.verifyEmail(TextUtils.noNull(details.getForwardEmail()).trim())) {
      errorCollection.addError("forwardEmail", i18nHelper.getText("admin.errors.invalid.email"));
    }
    return errorCollection;
  }
  @Test
  public void testNoFileProvided() throws Exception {
    expect(mockBeanFactory.getInstance(currentUser)).andReturn(mockI18nHelper).anyTimes();
    expect(mockPermissionManager.hasPermission(Permissions.SYSTEM_ADMIN, currentUser))
        .andReturn(true);
    expect(mockI18nHelper.getText("admin.errors.must.enter.xml2")).andReturn("Must provide file");

    try {
      final DataImportParams params = new DataImportParams.Builder("").build();
      executeTest(params, false, DataImportService.ImportError.NONE);
      fail("Calling doImport with invalid validation result should have thrown an exception!");
    } catch (IllegalStateException e) {
      // yay
    }
  }
  @Test
  public void testNoPermission() throws Exception {
    expect(mockBeanFactory.getInstance(currentUser)).andReturn(mockI18nHelper).anyTimes();
    expect(mockPermissionManager.hasPermission(Permissions.SYSTEM_ADMIN, currentUser))
        .andReturn(false);
    expect(mockI18nHelper.getText("admin.errors.import.permission"))
        .andReturn("No Permission to import data!");

    try {
      final String filePath = getDataFilePath("jira-export-test.xml");
      final DataImportParams params = new DataImportParams.Builder(filePath).build();
      executeTest(params, false, DataImportService.ImportError.NONE);
      fail("Calling doImport with invalid validation result should have thrown an exception!");
    } catch (IllegalStateException e) {
      // yay
    }
  }
  @Test
  public void testNoAO() throws Exception {
    expect(mockBeanFactory.getInstance(currentUser)).andReturn(mockI18nHelper).anyTimes();
    expect(mockPermissionManager.hasPermission(Permissions.SYSTEM_ADMIN, currentUser))
        .andReturn(true);
    expect(mockJiraHome.getImportDirectory()).andReturn(new File("somewhere")).anyTimes();
    expect(mockI18nHelper.getText("data.import.error.no.ao")).andReturn("Data Import.");

    backup = null;

    try {
      final String filePath = getDataFilePath("jira-export-test.xml");
      final DataImportParams params = new DataImportParams.Builder(filePath).build();
      executeTest(params, false, DataImportService.ImportError.NONE);
      fail("Calling doImport with invalid validation result should have thrown an exception!");
    } catch (IllegalStateException e) {
      // yay
    }
  }
  @Test
  public void testFileNonExistent() throws Exception {
    expect(mockBeanFactory.getInstance(currentUser)).andReturn(mockI18nHelper).anyTimes();
    expect(mockPermissionManager.hasPermission(Permissions.SYSTEM_ADMIN, currentUser))
        .andReturn(true);
    expect(mockJiraHome.getImportDirectory()).andReturn(new File("somewhere")).anyTimes();
    expect(
            mockI18nHelper.getText(
                EasyMock.eq("admin.errors.could.not.find.file"), EasyMock.<String>anyObject()))
        .andReturn("File does not exist.");

    try {
      final DataImportParams params =
          new DataImportParams.Builder("idontexisthopefully.txt").build();
      executeTest(params, false, DataImportService.ImportError.NONE);
      fail("Calling doImport with invalid validation result should have thrown an exception!");
    } catch (IllegalStateException e) {
      // yay
    }
  }
  private MappingResult validateAndAutoMapFields(
      final JiraServiceContext jiraServiceContext,
      final ProjectImportOptions projectImportOptions,
      final ProjectImportData projectImportData,
      final BackupProject backupProject,
      final BackupSystemInformation backupSystemInformation,
      final TaskProgressInterval taskProgressInterval) {
    log.info(
        "Project Import: Mapping the backed up data to data in the current system, and validating the mappings...");
    final MappingResult mappingResult = buildMappingResult();
    final I18nHelper i18n = jiraServiceContext.getI18nBean();

    // Step 2 Map and validate the Issue Types
    projectImportManager.autoMapAndValidateIssueTypes(
        projectImportData, mappingResult, backupProject, jiraServiceContext.getI18nBean());

    // If there is a problem processing the issue types then we don't want to do any further
    // mappings or validation
    if ((mappingResult.getIssueTypeMessageSet() != null)
        && !mappingResult.getIssueTypeMessageSet().hasAnyErrors()) {
      // Try to map the custom fields
      projectImportManager.autoMapAndValidateCustomFields(
          projectImportData, mappingResult, backupProject, i18n);

      if (!mappingResult.getCustomFieldMessageSet().hasAnyErrors()) {
        // Only map the system fields if we can move forward with the custom fields
        projectImportManager.autoMapSystemFields(projectImportData, backupProject);

        // Only map the project roles if we can move forward with the custom fields
        projectImportManager.autoMapProjectRoles(projectImportData);

        // Only map the custom field values once we know that the custom fields are good
        projectImportManager.autoMapCustomFieldOptions(projectImportData, backupProject);

        final boolean importAttachments =
            !StringUtils.isEmpty(projectImportOptions.getAttachmentPath());
        final int customFieldValuePercentage = (importAttachments) ? 60 : 90;
        // if we can successfully map the custom fields then lets validate the custom field values
        try {
          // Create a TaskProgressProcessor for validateCustomFieldValues
          final TaskProgressInterval subInterval =
              getSubInterval(taskProgressInterval, 0, customFieldValuePercentage);
          EntityCountTaskProgressProcessor taskProgressProcessor = null;
          if (taskProgressInterval != null) {
            taskProgressProcessor =
                new EntityCountTaskProgressProcessor(
                    subInterval,
                    i18n.getText(
                        "admin.message.project.import.manager.do.mapping.validate.custom.field.values"),
                    projectImportData.getCustomFieldValuesEntityCount(),
                    i18n);
          }
          projectImportManager.validateCustomFieldValues(
              projectImportData, mappingResult, backupProject, taskProgressProcessor, i18n);
        } catch (final IOException e) {
          log.error(
              "There was a problem accessing the file '"
                  + projectImportData.getPathToCustomFieldValuesXml()
                  + "' when performing a project import.",
              e);
          jiraServiceContext
              .getErrorCollection()
              .addErrorMessage(
                  getText(
                      i18n,
                      "admin.errors.project.import.problem.reading.custom.field.xml",
                      projectImportData.getPathToCustomFieldValuesXml()));
          return null;
        } catch (final SAXException e) {
          log.error(
              "There was a problem accessing the file '"
                  + projectImportData.getPathToCustomFieldValuesXml()
                  + "' when performing a project import.",
              e);
          jiraServiceContext
              .getErrorCollection()
              .addErrorMessage(
                  getText(
                      i18n,
                      "admin.errors.project.import.custom.field.sax.problem",
                      projectImportData.getPathToCustomFieldValuesXml(),
                      e.getMessage()));
          return null;
        }

        // Only validate the system field mappings after we have done all the rest
        // Create a sub interval of the taskProgressInterval we were given.
        TaskProgressInterval sysFieldSubInterval = null;
        if (taskProgressInterval != null) {
          sysFieldSubInterval =
              taskProgressInterval.getSubInterval(
                  customFieldValuePercentage, customFieldValuePercentage + 10);
        }
        projectImportManager.validateSystemFields(
            projectImportData,
            mappingResult,
            projectImportOptions,
            backupProject,
            sysFieldSubInterval,
            i18n);

        // Validate the attachments if we are importing attachments
        if (!importAttachments) {
          final MessageSet messageSet = new MessageSetImpl();
          messageSet.addWarningMessage(
              getText(i18n, "admin.warning.project.import.mapping.no.backup.atttachment.path"));
          log.warn(
              "File attachments will not be imported because you have not provided a backup attachment path.");
          mappingResult.setFileAttachmentMessageSet(messageSet);
        } else {
          try {
            // Create a TaskProgressProcessor for validateFileAttachments
            final TaskProgressInterval attachmentSubInterval =
                getSubInterval(taskProgressInterval, 70, 100);
            EntityCountTaskProgressProcessor taskProgressProcessor = null;
            if (taskProgressInterval != null) {
              taskProgressProcessor =
                  new EntityCountTaskProgressProcessor(
                      attachmentSubInterval,
                      i18n.getText(
                          "admin.message.project.import.manager.do.mapping.validate.file.attachment.values"),
                      projectImportData.getFileAttachmentEntityCount(),
                      i18n);
            }
            projectImportManager.validateFileAttachments(
                projectImportOptions,
                projectImportData,
                mappingResult,
                backupProject,
                backupSystemInformation,
                taskProgressProcessor,
                i18n);
          } catch (final IOException e) {
            log.error(
                "There was a problem accessing the file '"
                    + projectImportData.getPathToFileAttachmentXml()
                    + "' when performing a project import.",
                e);
            jiraServiceContext
                .getErrorCollection()
                .addErrorMessage(
                    getText(
                        i18n,
                        "admin.errors.project.import.problem.reading.attachment.xml",
                        projectImportData.getPathToFileAttachmentXml()));
            return null;
          } catch (final SAXException e) {
            log.error(
                "There was a problem accessing the file '"
                    + projectImportData.getPathToFileAttachmentXml()
                    + "' when performing a project import.",
                e);
            jiraServiceContext
                .getErrorCollection()
                .addErrorMessage(
                    getText(
                        i18n,
                        "admin.errors.project.import.custom.field.sax.problem",
                        projectImportData.getPathToFileAttachmentXml(),
                        e.getMessage()));
            return null;
          }
        }
      } else {
        // When the required custom fields have not passed validation we still want to show that
        // validation has
        // not happened for each of the custom field values.
        addCustomFieldValuesNotCheckedMessageSets(projectImportData, mappingResult);
      }
    } else {
      // When the required issue types have not passed validation we still want to show that
      // validation has
      // not happened for each of the custom field values.
      addCustomFieldValuesNotCheckedMessageSets(projectImportData, mappingResult);
    }

    // We want to populate the message list of the results. This puts the message results into order
    // and gives
    // them i18n header labels
    createValidationMessageList(mappingResult, projectImportData, i18n);

    if (mappingResult.canImport()) {
      log.info("Project Import: No validation errors were found and the import can continue.");
    } else {
      log.info("Project Import: Validation errors were found. The import cannot continue.");
    }
    return mappingResult;
  }
 String getText(final I18nHelper i18n, final String key, final String value1) {
   return i18n.getText(key, value1);
 }
 /// CLOVER:OFF
 String getText(final I18nHelper i18n, final String key) {
   return i18n.getText(key);
 }
  public ProjectImportResults doImport(
      final JiraServiceContext jiraServiceContext,
      final ProjectImportOptions projectImportOptions,
      final BackupProject backupProject,
      final BackupSystemInformation backupSystemInformation,
      final ProjectImportData projectImportData,
      final TaskProgressInterval taskProgressInterval) {
    Null.not("projectImportOptions", projectImportOptions);
    Null.not("backupSystemInformation", backupSystemInformation);
    Null.not("projectImportData", projectImportData);
    Null.not("backupProject", backupProject);
    validateJiraServiceContext(jiraServiceContext);
    final ErrorCollection errorCollection = jiraServiceContext.getErrorCollection();
    final I18nHelper i18n = jiraServiceContext.getI18nBean();

    // Get the expected number of users that we will create
    final int usersToCreate =
        (isExternalUserManagementEnabled())
            ? 0
            : projectImportData
                .getProjectImportMapper()
                .getUserMapper()
                .getUsersToAutoCreate()
                .size();

    final ProjectImportResults projectImportResults =
        getInitialImportResults(projectImportData, i18n, usersToCreate);

    // The user must have the system administrator permission to perform a project import
    if (!userHasSysAdminPermission(jiraServiceContext.getUser())) {
      errorCollection.addErrorMessage(getText(i18n, "admin.errors.project.import.must.be.admin"));
      return projectImportResults;
    }

    try {
      log.info(
          "Starting project import for project '" + backupProject.getProject().getKey() + "'.");
      if (isExternalUserManagementEnabled()) {
        log.info("External user management is enabled. No users will be imported.");
      } else {
        log.info(
            "Creating missing users. Attempting to create "
                + projectImportResults.getExpectedUsersCreatedCount()
                + " users.");
        // External User Management is OFF - create missing users that we can.
        // This will fill in subtask progress from 0% - 10% of the doImport task
        final TaskProgressInterval subInterval = getSubInterval(taskProgressInterval, 0, 10);
        projectImportManager.createMissingUsers(
            projectImportData.getProjectImportMapper().getUserMapper(),
            projectImportResults,
            subInterval);
        log.info(
            "Finished creating missing users. "
                + projectImportResults.getUsersCreatedCount()
                + " users created.");
      }

      // Create/Update the project, its details, components, versions, role membership
      try {
        // This will fill in subtask progress from 10% - 20% of the doImport task (Allow for
        // creating lots of Project Role members)
        final TaskProgressInterval subInterval = getSubInterval(taskProgressInterval, 10, 20);
        projectImportManager.importProject(
            projectImportOptions,
            projectImportData.getProjectImportMapper(),
            backupProject,
            projectImportResults,
            subInterval);
      } catch (final AbortImportException e) {
        // Add an error message
        errorCollection.addErrorMessage(
            i18n.getText("admin.error.project.import.project.update.error"));
        throw e;
      }

      // Import the issues and all their related values and reIndex the project once it is done
      try {
        // This will fill in subtask progress from 20% - 100% of the doImport task (Allow for
        // creating lots of Project Role members)
        final TaskProgressInterval subInterval = getSubInterval(taskProgressInterval, 20, 100);
        projectImportManager.doImport(
            projectImportOptions,
            projectImportData,
            backupProject,
            backupSystemInformation,
            projectImportResults,
            subInterval,
            i18n,
            jiraServiceContext.getUser());
        // Only set the completed flag once everything has finished
        projectImportResults.setImportCompleted(true);
      } catch (final IOException e) {
        log.error(
            "There was a problem accessing the partitioned XML files when performing a project import.",
            e);
        errorCollection.addErrorMessage(
            getText(
                i18n,
                "admin.errors.project.import.problem.reading.partitioned.xml",
                e.getMessage()));
      } catch (final AbortImportException aie) {
        // Note that AbortImportException extends SAXException, so we need to catch and handle
        // AbortImportException first.
        log.error("The import was aborted because there were too many errors.");
        errorCollection.addErrorMessage(i18n.getText("admin.errors.project.import.import.error"));
      } catch (final SAXException e) {
        log.error(
            "There was a problem accessing the partitioned XML files when performing a project import.",
            e);
        errorCollection.addErrorMessage(
            getText(
                i18n, "admin.errors.project.import.sax.problem.partitioned.xml", e.getMessage()));
      } catch (final IndexException e) {
        log.error("There was a problem reIndexing the newly imported project.", e);
        errorCollection.addErrorMessage(
            i18n.getText("admin.errors.project.import.reindex.problem", e.getMessage()));
      }
      log.info(
          "Finished project import for project '" + backupProject.getProject().getKey() + "'.");

    } catch (final AbortImportException aie) {
      log.error("The import was aborted because there were too many errors.");
      errorCollection.addErrorMessage(i18n.getText("admin.errors.project.import.import.error"));
    }

    // Clean up the temporary "partitioned" XML files.
    projectImportData.getTemporaryFiles().deleteTempFiles();

    // Always record the end of the import.
    projectImportResults.setEndTime(System.currentTimeMillis());
    logImportResults(projectImportResults);
    return projectImportResults;
  }
  void createValidationMessageList(
      final MappingResult mappingResult,
      final ProjectImportData projectImportData,
      final I18nHelper i18nHelper) {
    // create an ordered list of Validation Messages with translated Context names.
    final List systemFieldsMessageList = new ArrayList();
    // Issue Type
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("issue.field.issuetype"), mappingResult.getIssueTypeMessageSet()));
    // Custom Field
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("admin.project.import.custom.field.configuration"),
            mappingResult.getCustomFieldMessageSet()));
    // Status
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("issue.field.status"), mappingResult.getStatusMessageSet()));
    // Priority
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("issue.field.priority"), mappingResult.getPriorityMessageSet()));
    // Resolution
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("issue.field.resolution"), mappingResult.getResolutionMessageSet()));
    // Users
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("admin.common.words.users"), mappingResult.getUserMessageSet()));
    // ProjectRole
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("admin.common.words.projectrole"),
            mappingResult.getProjectRoleMessageSet()));
    // ProjectRoleActors
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("admin.common.words.projectrole.membership"),
            mappingResult.getProjectRoleActorMessageSet()));
    // Group
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("admin.common.words.group"), mappingResult.getGroupMessageSet()));
    // IssueLinkType
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("common.concepts.issuelinktype"),
            mappingResult.getIssueLinkTypeMessageSet()));
    // IssueSecurityLevel
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("admin.common.words.issue.security.level"),
            mappingResult.getIssueSecurityLevelMessageSet()));
    // File Attachments
    systemFieldsMessageList.add(
        new MappingResult.ValidationMessage(
            i18nHelper.getText("common.concepts.attachments.files"),
            mappingResult.getFileAttachmentMessageSet()));

    mappingResult.setSystemFieldsMessageList(systemFieldsMessageList);

    // Now find Custom Field Value messages
    final List customFieldsMessageList = new ArrayList();
    final CustomFieldMapper customFieldMapper =
        projectImportData.getProjectImportMapper().getCustomFieldMapper();
    for (final Iterator iterator =
            mappingResult.getCustomFieldValueMessageSets().keySet().iterator();
        iterator.hasNext(); ) {
      final String oldCustomFieldId = (String) iterator.next();
      final MessageSet messageSet =
          (MessageSet) mappingResult.getCustomFieldValueMessageSets().get(oldCustomFieldId);
      customFieldsMessageList.add(
          new MappingResult.ValidationMessage(
              customFieldMapper.getDisplayName(oldCustomFieldId), messageSet));
    }
    mappingResult.setCustomFieldsMessageList(customFieldsMessageList);
  }
  public ProjectImportData getProjectImportData(
      final JiraServiceContext jiraServiceContext,
      final ProjectImportOptions projectImportOptions,
      final BackupProject backupProject,
      final BackupSystemInformation backupSystemInformation,
      final TaskProgressInterval taskProgressInterval) {
    Null.not("backupProject", backupProject);
    Null.not("projectImportOptions", projectImportOptions);
    Null.not("backupSystemInformation", backupSystemInformation);
    validateJiraServiceContext(jiraServiceContext);

    // The user must have the system administrator permission to perform a project import
    if (!userHasSysAdminPermission(jiraServiceContext.getUser())) {
      jiraServiceContext
          .getErrorCollection()
          .addErrorMessage(
              getText(
                  jiraServiceContext.getI18nBean(), "admin.errors.project.import.must.be.admin"));
      return null;
    }

    final ErrorCollection errorCollection = jiraServiceContext.getErrorCollection();
    final I18nHelper i18n = jiraServiceContext.getI18nBean();
    final ProjectImportData projectImportData;
    try {
      // First step is to go through the import file again, populating our mappers and creating
      // partitioned XML files.
      // Create the Task Progress Processor for this subtask.
      EntityCountTaskProgressProcessor taskProgressProcessor = null;
      if (taskProgressInterval != null) {
        taskProgressProcessor =
            new EntityCountTaskProgressProcessor(
                taskProgressInterval,
                i18n.getText(
                    "admin.message.project.import.manager.do.mapping.extracting.project.data"),
                backupSystemInformation.getEntityCount(),
                i18n);
      }
      projectImportData =
          projectImportManager.getProjectImportData(
              projectImportOptions, backupProject, backupSystemInformation, taskProgressProcessor);
    } catch (final IOException e) {
      log.error(
          "There was a problem accessing the file '"
              + projectImportOptions.getPathToBackupXml()
              + "' when performing a project import.",
          e);
      errorCollection.addErrorMessage(
          getText(
              i18n,
              "admin.errors.project.import.problem.reading.backup",
              projectImportOptions.getPathToBackupXml()));
      return null;
    } catch (final SAXException e) {
      log.error(
          "There was a problem with the SAX parsing of the file '"
              + projectImportOptions.getPathToBackupXml()
              + "' when performing a project import.");
      errorCollection.addErrorMessage(
          getText(
              i18n,
              "admin.errors.project.import.sax.problem",
              projectImportOptions.getPathToBackupXml(),
              e.getMessage()));
      return null;
    }
    return projectImportData;
  }