/jira-project/jira-components/jira-plugins/jira-view-issue-plugin/src/main/java/com/atlassian/jira/plugin/viewissue/ActivityBlockViewIssueContextProvider.java
Java | 265 lines | 195 code | 49 blank | 21 comment | 28 complexity | 975f8077bb687e5036d5814f875b30c7 MD5 | raw file
Possible License(s): Apache-2.0
- package com.atlassian.jira.plugin.viewissue;
- import com.atlassian.event.api.EventPublisher;
- import com.atlassian.jira.config.properties.APKeys;
- import com.atlassian.jira.config.properties.ApplicationProperties;
- import com.atlassian.jira.issue.Issue;
- import com.atlassian.jira.plugin.issuetabpanel.GetActionsRequest;
- import com.atlassian.jira.plugin.issuetabpanel.IssueAction;
- import com.atlassian.jira.plugin.issuetabpanel.IssueTabPanelInvoker;
- import com.atlassian.jira.plugin.issuetabpanel.IssueTabPanelModuleDescriptor;
- import com.atlassian.jira.plugin.issuetabpanel.ShowPanelRequest;
- import com.atlassian.jira.plugin.util.ModuleDescriptorComparator;
- import com.atlassian.jira.plugin.viewissue.events.IssueTabRenderedEvent;
- import com.atlassian.jira.plugin.webfragment.CacheableContextProvider;
- import com.atlassian.jira.security.JiraAuthenticationContext;
- import com.atlassian.jira.user.ApplicationUser;
- import com.atlassian.jira.util.collect.MapBuilder;
- import com.atlassian.jira.util.velocity.VelocityRequestContext;
- import com.atlassian.jira.util.velocity.VelocityRequestContextFactory;
- import com.atlassian.jira.util.velocity.VelocityRequestSession;
- import com.atlassian.jira.web.SessionKeys;
- import com.atlassian.plugin.ModuleDescriptor;
- import com.atlassian.plugin.PluginAccessor;
- import com.atlassian.plugin.PluginParseException;
- import com.google.common.collect.ImmutableSet;
- import com.google.common.collect.Lists;
- import com.google.common.hash.Hashing;
- import org.apache.commons.lang.StringUtils;
- import org.apache.log4j.Logger;
- import java.nio.charset.Charset;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.stream.Collectors;
- /**
- * Context Provider for the Activity block section on View Issue page.
- * Expensive one so it cached per request/per user/per issue
- *
- * @since v4.4
- */
- public class ActivityBlockViewIssueContextProvider implements CacheableContextProvider {
- private static final String ORDER_DESC = "desc";
- protected final Logger log = Logger.getLogger(ActivityBlockViewIssueContextProvider.class);
- private final PluginAccessor pluginAccessor;
- private final JiraAuthenticationContext authenticationContext;
- private final VelocityRequestContextFactory requestContextFactory;
- private final ApplicationProperties applicationProperties;
- private final IssueTabPanelInvoker issueTabPanelInvoker;
- private final EventPublisher eventPublisher;
- private final Set<String> WHITELISTED_KEYS = ImmutableSet.of(
- "com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel",
- "com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel",
- "com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel",
- "com.atlassian.jira.plugin.system.issuetabpanels:changehistory-tabpanel",
- "com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab"
- );
- public ActivityBlockViewIssueContextProvider(PluginAccessor pluginAccessor, JiraAuthenticationContext authenticationContext,
- VelocityRequestContextFactory requestContextFactory, ApplicationProperties applicationProperties,
- IssueTabPanelInvoker issueTabPanelInvoker, EventPublisher eventPublisher) {
- this.pluginAccessor = pluginAccessor;
- this.authenticationContext = authenticationContext;
- this.requestContextFactory = requestContextFactory;
- this.applicationProperties = applicationProperties;
- this.issueTabPanelInvoker = issueTabPanelInvoker;
- this.eventPublisher = eventPublisher;
- }
- @Override
- public void init(Map<String, String> params) throws PluginParseException {
- }
- @Override
- public Map<String, Object> getContextMap(Map<String, Object> context) {
- boolean isAsynchronous = (Boolean) consumeParam(context, "isAsynchronousRequest");
- final Issue issue = (Issue) context.get("issue");
- final ApplicationUser user = authenticationContext.getUser();
- final MapBuilder<String, Object> paramsBuilder = MapBuilder.newBuilder(context);
- final ArrayList<IssueTabPanelModuleDescriptor> tabPanelDescriptors = getTabPanels(issue, user);
- String currentPageKey = getCurrentTabPanel(tabPanelDescriptors);
- IssueTabPanelModuleDescriptor currentTabPanelModuleDescriptor = getTabPanelModuleDescriptor(currentPageKey, tabPanelDescriptors);
- final String actionSortOrder = getActionSortOrder();
- final VelocityRequestContext requestContext = requestContextFactory.getJiraVelocityRequestContext();
- boolean showAllFlag = (requestContext.getRequestParameter("showAll") != null);
- String focusId = requestContext.getRequestParameter("focusedCommentId");
- GetActionsRequest getActionsRequest = new GetActionsRequest(issue, user, isAsynchronous, showAllFlag, focusId);
- List<IssueAction> issueActions = issueTabPanelInvoker.invokeGetActions(getActionsRequest, currentTabPanelModuleDescriptor);
- final List<IssueAction> actions = Lists.newArrayList(issueActions);
- sort(actions, actionSortOrder);
- paramsBuilder.add("tabPanels", tabPanelDescriptors);
- paramsBuilder.add("hasPanels", !tabPanelDescriptors.isEmpty());
- paramsBuilder.add("currentPageKey", currentPageKey);
- paramsBuilder.add("currentTab", currentTabPanelModuleDescriptor);
- paramsBuilder.add("isSortable", currentTabPanelModuleDescriptor.isSortable() && actions != null && actions.size() > 1);
- paramsBuilder.add("actions", actions);
- paramsBuilder.add("hasActions", actions != null && !actions.isEmpty());
- paramsBuilder.add("actionError", actions == null);
- paramsBuilder.add("actionsSortOrder", actionSortOrder);
- sendTabRenderedEvent(currentPageKey, tabPanelDescriptors, issue);
- return paramsBuilder.toMap();
- }
- @Override
- public String getUniqueContextKey(Map<String, Object> context) {
- final Issue issue = (Issue) context.get("issue");
- final ApplicationUser user = authenticationContext.getUser();
- return issue.getId() + "/" + (user == null ? "" : user.getName());
- }
- private void sort(List<IssueAction> actions, String actionSortOrder) {
- if (ORDER_DESC.equals(actionSortOrder)) {
- Collections.reverse(actions);
- }
- }
- private String getActionSortOrder() {
- final String defaultOrder = applicationProperties.getDefaultBackedString(APKeys.JIRA_ISSUE_ACTIONS_ORDER);
- final VelocityRequestContext requestContext = requestContextFactory.getJiraVelocityRequestContext();
- String actionOrder = requestContext.getRequestParameter("actionOrder");
- final VelocityRequestSession session = requestContext.getSession();
- if (StringUtils.isNotBlank(actionOrder)) {
- if (!actionOrder.equals(defaultOrder)) {
- session.setAttribute(SessionKeys.VIEWISSUE_ACTION_ORDER, actionOrder);
- return actionOrder;
- }
- session.removeAttribute(SessionKeys.VIEWISSUE_ACTION_ORDER);
- return defaultOrder;
- }
- actionOrder = (String) session.getAttribute(SessionKeys.VIEWISSUE_ACTION_ORDER);
- if (StringUtils.isNotBlank(actionOrder)) {
- return actionOrder;
- }
- return defaultOrder;
- }
- private String getCurrentTabPanel(List<IssueTabPanelModuleDescriptor> tabPanels) {
- final VelocityRequestContext requestContext = requestContextFactory.getJiraVelocityRequestContext();
- String page = requestContext.getRequestParameter("page");
- final VelocityRequestSession session = requestContext.getSession();
- if (StringUtils.isNotBlank(page) && isTabPanelVisisble(page, tabPanels)) {
- session.setAttribute(SessionKeys.VIEWISSUE_PAGE, page);
- return page;
- }
- page = (String) session.getAttribute(SessionKeys.VIEWISSUE_PAGE);
- if (StringUtils.isNotBlank(page) && isTabPanelVisisble(page, tabPanels)) {
- return page;
- }
- return getDefaultPage(tabPanels);
- }
- private boolean isTabPanelVisisble(String tabPanelKey, List<IssueTabPanelModuleDescriptor> tabPanels) {
- return getTabPanelModuleDescriptor(tabPanelKey, tabPanels) != null;
- }
- private IssueTabPanelModuleDescriptor getTabPanelModuleDescriptor(String key, List<IssueTabPanelModuleDescriptor> tabPanels) {
- for (IssueTabPanelModuleDescriptor tabPanel : tabPanels) {
- if (tabPanel.getCompleteKey().equals(key)) {
- return tabPanel;
- }
- }
- return null;
- }
- private ArrayList<IssueTabPanelModuleDescriptor> getTabPanels(Issue issue, ApplicationUser user) {
- final List<IssueTabPanelModuleDescriptor> allTabPanels = pluginAccessor.getEnabledModuleDescriptorsByClass(IssueTabPanelModuleDescriptor.class);
- final ArrayList<IssueTabPanelModuleDescriptor> filteredTabPanels = Lists.newArrayListWithCapacity(allTabPanels.size());
- for (IssueTabPanelModuleDescriptor descriptor : allTabPanels) {
- if (issueTabPanelInvoker.invokeShowPanel(new ShowPanelRequest(issue, user), descriptor)) {
- filteredTabPanels.add(descriptor);
- }
- }
- Collections.sort(filteredTabPanels, ModuleDescriptorComparator.COMPARATOR);
- return filteredTabPanels;
- }
- private void sendTabRenderedEvent(final String currentPageKey, final List<IssueTabPanelModuleDescriptor> moduleDescriptors,
- final Issue issue) {
- if (currentPageKey == null) {
- return;
- }
- final int tabIndex = moduleDescriptors.stream()
- .map(ModuleDescriptor::getCompleteKey)
- .collect(Collectors.toList())
- .indexOf(currentPageKey);
- // whitelist tab name
- String whitelistedTabKey = currentPageKey;
- if (!WHITELISTED_KEYS.contains(currentPageKey)) {
- whitelistedTabKey = Hashing.md5()
- .newHasher().putString(currentPageKey, Charset.defaultCharset()).hash()
- .toString();
- }
- final IssueTabRenderedEvent event = new IssueTabRenderedEvent(whitelistedTabKey, tabIndex, issue.getId());
- eventPublisher.publish(event);
- }
- /**
- * @param issueTabPanels a List<IssueTabPanelModuleDescriptor>
- * @return the default page (as specified by the {@link IssueTabPanelModuleDescriptor})
- * @see com.atlassian.jira.plugin.issuetabpanel.IssueTabPanelModuleDescriptor#isDefault()
- */
- private String getDefaultPage(List<IssueTabPanelModuleDescriptor> issueTabPanels) {
- for (final IssueTabPanelModuleDescriptor descriptor : issueTabPanels) {
- if (descriptor.isDefault()) {
- return descriptor.getCompleteKey();
- }
- }
- // if no defaults are found, then just return the first one (if there are any)
- if (!issueTabPanels.isEmpty()) {
- return issueTabPanels.get(0).getCompleteKey();
- } else {
- return null;
- }
- }
- /**
- * Helper method used to consumer context parameters that we don't want to propagate into the issue tab panel
- * velocity context.
- *
- * @param context the context map
- * @param paramName the name of the parameter
- * @return <code>context</code> minus the entry with key=<code>paramName</code>
- */
- private Object consumeParam(Map<String, Object> context, String paramName) {
- Object result = context.get(paramName);
- context.remove(paramName);
- return result;
- }
- }