private void validateExistingProjectHasValidStateForImport(
      final BackupProject backupProject,
      final BackupSystemInformation backupSystemInformation,
      final Project existingProject,
      final I18nHelper i18n,
      final MessageSet messageSet) {
    final String projectKey = backupProject.getProject().getKey();

    // Verify that the project has no existing issues
    final long issueCount = issueManager.getIssueCountForProject(existingProject.getId());
    if (issueCount != 0) {
      messageSet.addErrorMessage(
          getText(
              i18n,
              "admin.error.project.import.project.contains.issues",
              projectKey,
              String.valueOf(issueCount)));
    }

    // Verify that the project has no existing versions
    final long versionCount = versionManager.getVersions(existingProject.getId()).size();
    if (versionCount != 0) {
      messageSet.addErrorMessage(
          getText(
              i18n,
              "admin.error.project.import.project.contains.versions",
              projectKey,
              String.valueOf(versionCount)));
    }

    // Verify that the project has no existing components
    final long componentCount =
        projectComponentManager.findAllForProject(existingProject.getId()).size();
    if (componentCount != 0) {
      messageSet.addErrorMessage(
          getText(
              i18n,
              "admin.error.project.import.project.contains.components",
              projectKey,
              String.valueOf(componentCount)));
    }

    // Verify that if the project has a default assignee of Unassigned that the current instance of
    // JIRA supports unassigned issues
    if (projectHasDefaultAssigneeUnassigned(backupProject, backupSystemInformation)) {
      // We want this instance of JIRA to allow unassigned issues.
      final boolean allowUnassigned =
          applicationProperties.getOption(APKeys.JIRA_OPTION_ALLOWUNASSIGNED);
      if (!allowUnassigned) {
        messageSet.addErrorMessage(
            getText(
                i18n,
                "admin.error.project.import.project.default.assignee.not.allowed",
                backupProject.getProject().getName()));
      }
    }
  }
  @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));
            }
          }
        }
      }
    }
  }
 private boolean checkWorkflow(
     final boolean equality,
     final Set<String> ids,
     final Project project,
     final String issueType,
     final String workflowName) {
   final JiraWorkflow workflow = workflowManager.getWorkflow(workflowName);
   if (workflow != null) {
     final List<Status> statusObjects = workflow.getLinkedStatusObjects();
     for (Status statusObject : statusObjects) {
       // JRA-19026 - when we encounter really messed up data the workflow can return null statuses
       if (statusObject != null) {
         if (equality == ids.contains(statusObject.getId())) {
           return true;
         }
       } else {
         final String issueTypeStr = issueType == null ? "default" : issueType;
         // Kinda strange, probably means you manually messed with your workflow, lets info log
         log.info(
             "Workflow: '"
                 + workflow.getName()
                 + "' associated with project: '"
                 + project.getId()
                 + "' and issue type: '"
                 + issueTypeStr
                 + "' contains a null status, you might want to fix that.");
       }
     }
   }
   return false;
 }
 private Set<ProjectIssueTypeContext> getContextsForProjects(final Collection<Project> projects) {
   CollectionBuilder<ProjectIssueTypeContext> builder = CollectionBuilder.newBuilder();
   for (Project project : projects) {
     builder.add(
         new ProjectIssueTypeContextImpl(
             new ProjectContextImpl(project.getId()), AllIssueTypesContext.INSTANCE));
   }
   return builder.asMutableSet();
 }
  public Map<String, String> getAllProjects() {
    Map<String, String> allProjs = new TreeMap<String, String>();

    List<Project> projs = prMgr.getProjectObjects();
    if (projs != null) {
      for (Project proj : projs) {
        allProjs.put(proj.getId().toString(), getProjView(proj.getName(), proj.getDescription()));
      }
    }

    return allProjs;
  }
  public void testGetProjectIds() {
    expect(ctx.getLoggedInUser()).andReturn(mockUser);
    Project project = createNiceMock(Project.class);
    expect(project.getId()).andReturn(666L);
    Project project2 = createNiceMock(Project.class);
    expect(project2.getId()).andReturn(323L);
    expect(proj.getProjectObj(666L)).andReturn(project);
    expect(proj.getProjectObj(323L)).andReturn(project2);
    expect(prms.hasPermission(Permissions.BROWSE, project, mockUser)).andReturn(true);
    expect(prms.hasPermission(Permissions.BROWSE, project2, mockUser)).andReturn(true);

    expect(proj.getProjectObjectsFromProjectCategory(555L)).andReturn(Arrays.asList(project2));

    EasyMock.replay(ctx, prms, proj, project, project2);

    ProjectsAndCategoriesHelper helper = new DefaultProjectsAndCategoriesHelper(proj, prms, ctx);

    Set<Long> ids = helper.getProjectIds("666|cat555");
    assertNotNull(ids);
    assertEquals(1, ids.size());
  }
  private Set<ProjectIssueTypeContext> getContextsForIssueType(
      final Project project, final Map<String, String> schemeMap, final String issueType) {
    // Null issue type means "default" issues types.
    if (issueType == null) {
      Set<ProjectIssueTypeContext> contexts = new HashSet<ProjectIssueTypeContext>();

      final Collection<IssueType> projectTypes =
          issueTypeSchemeManager.getIssueTypesForProject(project);
      for (IssueType projectType : projectTypes) {
        if (projectType != null && !schemeMap.containsKey(projectType.getId())) {
          contexts.add(
              new ProjectIssueTypeContextImpl(
                  new ProjectContextImpl(project.getId()),
                  new IssueTypeContextImpl(projectType.getId())));
        }
      }
      return contexts;
    } else {
      return Collections.<ProjectIssueTypeContext>singleton(
          new ProjectIssueTypeContextImpl(
              new ProjectContextImpl(project.getId()), new IssueTypeContextImpl(issueType)));
    }
  }
  public void testGetProjectIdsWithAll() {
    expect(ctx.getLoggedInUser()).andReturn(mockUser);
    Project project = createNiceMock(Project.class);
    expect(project.getId()).andReturn(666L);
    expect(prms.getProjectObjects(Permissions.BROWSE, mockUser)).andReturn(Arrays.asList(project));

    EasyMock.replay(ctx, prms, proj, project);

    ProjectsAndCategoriesHelper helper = new DefaultProjectsAndCategoriesHelper(proj, prms, ctx);

    Set<Long> ids = helper.getProjectIds("allprojects");
    assertNotNull(ids);
    assertEquals(1, ids.size());
  }
  protected FieldMetaBean getFieldMetaBean(
      boolean required, OrderableField field, boolean forceRequired) {
    Collection<String> operations;
    if (field instanceof RestFieldOperations) {
      operations = ((RestFieldOperations) field).getRestFieldOperation().getSupportedOperations();
    } else {
      operations = Collections.emptyList();
    }
    Collection<?> allowedValues = null;
    FieldTypeInfo fieldTypeInfo;
    JsonType jsonType;

    if (field instanceof RestAwareField) {
      FieldTypeInfoContext fieldTypeInfoContext =
          new FieldTypeInfoContextImpl(
              field,
              issue,
              new IssueContextImpl(project.getId(), issueType.getId()),
              getOperationContext());
      fieldTypeInfo = ((RestAwareField) field).getFieldTypeInfo(fieldTypeInfoContext);
      jsonType = getJsonType((RestAwareField) field);
      allowedValues = getAllowedValueBeans(field, fieldTypeInfo.getAllowedValues());
    } else if (field instanceof CustomField) {
      CustomField customField = (CustomField) field;
      fieldTypeInfo = new FieldTypeInfo(null, null);
      jsonType = getJsonType(customField);
    } else {
      fieldTypeInfo = new FieldTypeInfo(null, null);
      jsonType = null;
    }
    return new FieldMetaBean(
        required || forceRequired,
        jsonType,
        field.getName(),
        fieldTypeInfo.getAutoCompleteUrl(),
        operations,
        allowedValues);
  }
  @EventListener
  public void onIssueEvent(IssueEvent issueEvent) {
    if (!issueEvent.getEventTypeId().equals(EventType.ISSUE_CREATED_ID)) {
      return;
    }

    Issue issue = issueEvent.getIssue();
    Collection<ProjectComponent> comps = issue.getComponentObjects();
    if (comps == null || comps.size() < 2) {
      return;
    }

    Project project = issue.getProjectObject();
    if (project == null || !isApplyPlugin(project.getId())) {
      return;
    }

    List<Issue> newIssues = new ArrayList<Issue>();
    ProjectComponent gv = null;
    Iterator<ProjectComponent> iter = comps.iterator();
    while (iter.hasNext()) {
      gv = iter.next();

      MutableIssue nissue = ComponentManager.getInstance().getIssueFactory().getIssue();
      // --> summary
      nissue.setSummary(String.format("[%s] %s", gv.getName(), issue.getSummary()));
      // --> project
      if (issue.getProjectObject() != null) {
        nissue.setProjectId(issue.getProjectObject().getId());
      }
      // --> issue type
      if (issue.getIssueTypeObject() != null) {
        nissue.setIssueTypeId(issue.getIssueTypeObject().getId());
      }
      // --> components
      Collection<ProjectComponent> nComps = new LinkedList<ProjectComponent>();
      nComps.add(gv);
      nissue.setComponentObjects(nComps);
      // --> assignee
      String compLead = gv.getLead();
      nissue.setAssigneeId(compLead);
      // --> reporter
      nissue.setReporter(issueEvent.getUser());
      // --> priority
      nissue.setPriorityObject(issue.getPriorityObject());
      // --> description
      nissue.setDescription(issue.getDescription());
      // --> env
      nissue.setEnvironment(issue.getEnvironment());
      // --> due date
      nissue.setDueDate(issue.getDueDate());
      // --> estimate
      nissue.setEstimate(issue.getEstimate());
      // --> labels
      nissue.setLabels(issue.getLabels());
      nissue.setAffectedVersions(issue.getAffectedVersions());
      nissue.setWorkflowId(issue.getWorkflowId());
      nissue.setParentId(issue.getParentId());

      // --> status
      if (issue.getStatusObject() != null) {
        nissue.setStatusId(issue.getStatusObject().getId());
      }

      // --> resolution
      if (issue.getResolutionObject() != null) {
        nissue.setResolutionId(issue.getResolutionObject().getId());
      }

      nissue.setFixVersions(issue.getFixVersions());
      nissue.setResolutionDate(issue.getResolutionDate());
      nissue.setTimeSpent(issue.getTimeSpent());
      nissue.setVotes(issue.getVotes());
      nissue.setCreated(issue.getCreated());
      nissue.setSecurityLevelId(issue.getSecurityLevelId());
      nissue.setOriginalEstimate(issue.getOriginalEstimate());

      List<CustomField> cfs =
          ComponentManager.getInstance().getCustomFieldManager().getCustomFieldObjects(issue);
      if (cfs != null) {
        for (CustomField cf : cfs) {
          Object cfVal = issue.getCustomFieldValue(cf);
          if (cfVal != null) {
            nissue.setCustomFieldValue(cf, cfVal);
          }
        }
      }

      // --> create issue
      try {
        Issue newIssueObj =
            ComponentManager.getInstance()
                .getIssueManager()
                .createIssueObject(issueEvent.getUser(), nissue);
        newIssues.add(newIssueObj);
      } catch (CreateException crex) {
        log.error("IssueClonerByComponents::onIssueEvent - Cannot create dependent issues", crex);
      }
    }

    Collection<Attachment> atts = issue.getAttachments();
    if (atts != null) {
      AttachmentManager am = ComponentManager.getInstance().getAttachmentManager();
      for (Attachment att : atts) {
        File attFile = AttachmentUtils.getAttachmentFile(att);
        String filename = att.getFilename();
        String contentType = att.getMimetype();
        for (Issue nissue : newIssues) {
          File newFile = new File(attFile.getAbsolutePath() + nissue.getKey());
          try {
            FileUtils.copyFile(attFile, newFile);
            am.createAttachment(newFile, filename, contentType, issueEvent.getUser(), nissue);
          } catch (Exception ex) {
            log.error("IssueClonerByComponents::onIssueEvent - Cannot copy attachment", ex);
          }
        }
      }
    }

    IssueLinkTypeManager issueLinkTypeManager =
        ComponentManager.getComponentInstanceOfType(IssueLinkTypeManager.class);
    Collection<IssueLinkType> types = issueLinkTypeManager.getIssueLinkTypesByName(LINK_TYPE);
    if (types == null || types.isEmpty()) {
      return;
    }

    IssueLinkType ilt = types.iterator().next();
    if (ilt != null) {
      IssueLinkManager ilm = ComponentManager.getInstance().getIssueLinkManager();
      for (Issue nissue : newIssues) {
        try {
          ilm.createIssueLink(
              issue.getId(), nissue.getId(), ilt.getId(), null, issueEvent.getUser());
        } catch (CreateException crex) {
          log.error("IssueClonerByComponents::onIssueEvent - Cannot create link", crex);
        }
      }
    }
  }
  @Override
  public boolean handleMessage(Message message, MessageHandlerContext context)
      throws MessagingException {
    log.debug("CreateIssueHandler.handleMessage");

    if (!canHandleMessage(message, context.getMonitor())) {
      return deleteEmail;
    }

    try {
      // get either the sender of the message, or the default reporter
      User reporter = getReporter(message, context);

      // no reporter - so reject the message
      if (reporter == null) {
        final String error = getI18nBean().getText("admin.mail.no.default.reporter");
        context.getMonitor().warning(error);
        context.getMonitor().messageRejected(message, error);
        return false;
      }

      final Project project = getProject(message);

      log.debug("Project = " + project);
      if (project == null) {
        final String text = getI18nBean().getText("admin.mail.no.project.configured");
        context.getMonitor().warning(text);
        context.getMonitor().messageRejected(message, text);
        return false;
      }

      // Check that the license is valid before allowing issues to be created
      // This checks for: evaluation licenses expired, user limit licenses where limit has been
      // exceeded
      ErrorCollection errorCollection = new SimpleErrorCollection();
      // Note: want English locale here for logging purposes
      I18nHelper i18nHelper = new I18nBean(Locale.ENGLISH);

      getIssueCreationHelperBean().validateLicense(errorCollection, i18nHelper);
      if (errorCollection.hasAnyErrors()) {
        context
            .getMonitor()
            .warning(
                getI18nBean()
                    .getText(
                        "admin.mail.bad.license", errorCollection.getErrorMessages().toString()));
        return false;
      }

      // If user does not have create permissions, there's no point proceeding. Error out here to
      // avoid a stack
      // trace blow up from the WorkflowManager later on.
      if (!getPermissionManager().hasPermission(Permissions.CREATE_ISSUE, project, reporter, true)
          && reporter.getDirectoryId() != -1) {
        final String error =
            getI18nBean().getText("admin.mail.no.create.permission", reporter.getName());
        context.getMonitor().warning(error);
        context.getMonitor().messageRejected(message, error);
        return false;
      }

      log.debug("Issue Type Key = = " + issueType);

      if (!hasValidIssueType()) {
        context.getMonitor().warning(getI18nBean().getText("admin.mail.invalid.issue.type"));
        return false;
      }
      String summary = message.getSubject();
      if (!TextUtils.stringSet(summary)) {
        context.getMonitor().error(getI18nBean().getText("admin.mail.no.subject"));
        return false;
      }
      if (summary.length() > SummarySystemField.MAX_LEN.intValue()) {
        context.getMonitor().info("Truncating summary field because it is too long: " + summary);
        summary = summary.substring(0, SummarySystemField.MAX_LEN.intValue() - 3) + "...";
      }

      // JRA-7646 - check if priority/description is hidden - if so, do not set
      String priority = null;
      String description = null;

      if (!getFieldVisibilityManager()
          .isFieldHiddenInAllSchemes(
              project.getId(),
              IssueFieldConstants.PRIORITY,
              Collections.singletonList(issueType))) {
        priority = getPriority(message);
      }

      if (!getFieldVisibilityManager()
          .isFieldHiddenInAllSchemes(
              project.getId(),
              IssueFieldConstants.DESCRIPTION,
              Collections.singletonList(issueType))) {
        description = getDescription(reporter, message);
      }

      MutableIssue issueObject = getIssueFactory().getIssue();
      issueObject.setProjectObject(project);
      issueObject.setSummary(summary);
      issueObject.setDescription(description);
      issueObject.setIssueTypeId(issueType);
      issueObject.setReporter(reporter);

      // if no valid assignee found, attempt to assign to default assignee
      User assignee = null;
      if (ccAssignee) {
        assignee = getFirstValidAssignee(message.getAllRecipients(), project);
      }
      if (assignee == null) {
        assignee = getAssigneeResolver().getDefaultAssignee(issueObject, Collections.EMPTY_MAP);
      }

      if (assignee != null) {
        issueObject.setAssignee(assignee);
      }

      issueObject.setPriorityId(priority);

      // Ensure issue level security is correct
      setDefaultSecurityLevel(issueObject);

      /*
       * + FIXME -- set cf defaults @todo +
       */
      // set default custom field values
      // CustomFieldValuesHolder cfvh = new CustomFieldValuesHolder(issueType, project.getId());
      // fields.put("customFields", CustomFieldUtils.getCustomFieldValues(cfvh.getCustomFields()));
      Map<String, Object> fields = new HashMap<String, Object>();
      fields.put("issue", issueObject);
      // TODO: How is this supposed to work? There is no issue created yet; ID = null.
      // wseliga note: Ineed I think that such call does not make sense - it will be always null
      MutableIssue originalIssue = getIssueManager().getIssueObject(issueObject.getId());

      // Give the CustomFields a chance to set their default values JRA-11762
      List<CustomField> customFieldObjects =
          ComponentAccessor.getCustomFieldManager().getCustomFieldObjects(issueObject);
      for (CustomField customField : customFieldObjects) {
        issueObject.setCustomFieldValue(customField, customField.getDefaultValue(issueObject));
      }

      fields.put(WorkflowFunctionUtils.ORIGINAL_ISSUE_KEY, originalIssue);
      final Issue issue = context.createIssue(reporter, issueObject);

      if (issue != null) {
        // Add Cc'ed users as watchers if params set - JRA-9983
        if (ccWatcher) {
          addCcWatchersToIssue(message, issue, reporter, context, context.getMonitor());
        }

        // Record the message id of this e-mail message so we can track replies to this message
        // and associate them with this issue
        recordMessageId(
            MailThreadManager.ISSUE_CREATED_FROM_EMAIL, message, issue.getId(), context);
      }

      // TODO: if this throws an error, then the issue is already created, but the email not deleted
      // - we will keep "handling" this email over and over :(
      createAttachmentsForMessage(message, issue, context);

      return true;
    } catch (Exception e) {
      context.getMonitor().warning(getI18nBean().getText("admin.mail.unable.to.create.issue"), e);
    }

    // something went wrong - don't delete the message
    return false;
  }
  Set<ProjectIssueTypeContext> getContextFromStatusValues(
      final User searcher, final TerminalClause clause, final boolean equality) {
    // if we don't have any ids, then the result will always be global: either by an empty set or
    // the everything set
    Set<String> ids = getIds(searcher, clause);
    if (ids.isEmpty()) {
      return Collections.emptySet();
    }

    boolean allProjects = true;
    boolean allIssueTypesAcrossAllProjects = true;

    final Map<String, Boolean> resultCache = new HashMap<String, Boolean>();
    final Set<ProjectIssueTypeContext> allContexts = new HashSet<ProjectIssueTypeContext>();
    final Collection<Project> projects =
        permissionManager.getProjectObjects(Permissions.BROWSE, searcher);

    for (final Project project : projects) {
      boolean projectAdded = false; // is this project added to the contxt
      boolean allIssueTypesAcrossProject =
          true; // are ALL issue types of this project added to the context
      Set<ProjectIssueTypeContext> projectIssueTypeContexts =
          new HashSet<ProjectIssueTypeContext>();

      // IssueType -> Workflowname
      final Map<String, String> workflowMap = workflowSchemeManager.getWorkflowMap(project);
      for (Map.Entry<String, String> entry : workflowMap.entrySet()) {
        final boolean typeAdded;
        final String issueType = entry.getKey();
        final String workflowName = entry.getValue();

        final Boolean cachedResult = resultCache.get(workflowName);
        if (cachedResult != null) {
          typeAdded = cachedResult;
        } else {
          typeAdded = checkWorkflow(equality, ids, project, issueType, workflowName);
          resultCache.put(workflowName, typeAdded);
        }

        if (typeAdded) {
          projectIssueTypeContexts.addAll(getContextsForIssueType(project, workflowMap, issueType));
          projectAdded = true;
        } else {
          allIssueTypesAcrossAllProjects = false;
          allIssueTypesAcrossProject = false;
        }
      }

      if (allIssueTypesAcrossProject) // if all issue types were added, its an ALL issue type
      // context type
      {
        projectIssueTypeContexts =
            Collections.<ProjectIssueTypeContext>singleton(
                new ProjectIssueTypeContextImpl(
                    new ProjectContextImpl(project.getId()), AllIssueTypesContext.INSTANCE));
      }
      if (!projectAdded) {
        allProjects = false;
      }
      allContexts.addAll(projectIssueTypeContexts);
    }

    if (allProjects
        && allIssueTypesAcrossAllProjects) // if all ALL projects and ALL issue types were added to
    // the context, it is an ALL ALL context type
    {
      return Collections.singleton(ProjectIssueTypeContextImpl.createGlobalContext());
    } else {
      return allContexts;
    }
  }
Beispiel #13
0
 public AffectedProject(final Project project) {
   this.projectId = project.getId();
   this.projectName = project.getName();
 }