RssFeedController.java
package org.itracker.web.servlets;
import com.sun.syndication.feed.module.DCModuleImpl;
import com.sun.syndication.feed.module.SyModuleImpl;
import com.sun.syndication.feed.rss.*;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.config.ForwardConfig;
import org.apache.struts.config.ModuleConfig;
import org.apache.struts.taglib.TagUtils;
import org.apache.struts.util.ModuleUtils;
import org.itracker.core.resources.ITrackerResources;
import org.itracker.model.Issue;
import org.itracker.model.IssueHistory;
import org.itracker.model.PermissionType;
import org.itracker.model.Project;
import org.itracker.model.util.IssueUtilities;
import org.itracker.services.ConfigurationService;
import org.itracker.services.IssueService;
import org.itracker.services.ProjectService;
import org.itracker.web.util.Constants;
import org.itracker.web.util.HTMLUtilities;
import org.itracker.web.util.LoginUtilities;
import org.itracker.web.util.ServletContextUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import javax.mail.internet.InternetAddress;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RssFeedController extends GenericController {
final private static Pattern URL_PATTERN = Pattern.compile("(?i).*/issues/p?([0-9]*)/?i?([0-9]*)");
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
RssChannelHttpMessageConverter conv = new RssChannelHttpMessageConverter();
try (ServletServerHttpResponse sr = new ServletServerHttpResponse(resp)) {
Matcher uriMatcher = URL_PATTERN.matcher(req.getRequestURI());
Integer projectId = null;
Integer issueId = null;
try {
if (uriMatcher.matches()) {
projectId = uriMatcher.group(1).equals("") ? null : Integer.valueOf(uriMatcher.group(1));
issueId = uriMatcher.group(2).equals("") ? null : Integer.valueOf(uriMatcher.group(2));
}
} catch (RuntimeException e) {
deny(sr);
return;
}
final IssueService is = ServletContextUtils.getItrackerServices().getIssueService();
final ProjectService ps = ServletContextUtils.getItrackerServices().getProjectService();
final ConfigurationService cs = ServletContextUtils.getItrackerServices().getConfigurationService();
final String baseURL = cs.getSystemBaseURL();
final String generator = cs.getProperty("notification_from_text",
"iTracker "
+ cs.getProperty(Constants.VERSION_KEY, "3"));
Channel c = new Channel(conv.getSupportedMediaTypes().get(0).getType());
c.setGenerator(generator);
c.setModules(Arrays.asList(
new DCModuleImpl(),
new SyModuleImpl()
));
c.setFeedType("rss_2.0");
c.setLink(cs.getSystemBaseURL() + req.getServletPath());
if (null != issueId) {
Issue i = is.getIssue(issueId);
if (!LoginUtilities.canViewIssue(i)) {
deny(sr);
return;
}
toChannel(c, i, baseURL);
} else if (null != projectId) {
Project p = ps.getProject(projectId);
if (null == p) {
deny(sr);
return;
}
if (!LoginUtilities.hasPermission(p, PermissionType.ISSUE_VIEW_USERS)) {
deny(sr);
return;
}
toChannel(c, p, is, req, baseURL);
} else {
toChannel(c, ps, req, baseURL);
}
conv.write(c, conv.getSupportedMediaTypes().get(0), sr);
}
}
private void toChannel(Channel c, ProjectService ps, HttpServletRequest req, String baseURL) {
List<Project> projects = ps.getAllAvailableProjects();
c.setTitle(ITrackerResources.getString("itracker.feed.projects.title"));
c.setDescription(ITrackerResources.getString("itracker.feed.projects.description", baseURL));
c.setLink(baseURL);
c.setUri(baseURL);
for (Project p : projects) {
if (LoginUtilities.hasAnyPermission(p, null)) {
Item pi = new Item();
pi.setLink(getProjectURL(p, req, getServletContext(), baseURL));
pi.setTitle(p.getName());
Guid guid = new Guid();
guid.setValue(pi.getLink());
guid.setPermaLink(true);
pi.setGuid(guid);
Description desc = new Description();
desc.setType(Content.TEXT);
desc.setValue(p.getDescription());
pi.setDescription(desc);
Content content = new Content();
content.setType(Content.HTML);
content.setValue(
p.getDescription()
);
pi.setPubDate(ps.getLatestIssueUpdatedDateByProjectId(p.getId()));
c.getItems().add(pi);
}
}
}
private void toChannel(Channel channel, Project project, IssueService is, HttpServletRequest req, String baseURL) throws MalformedURLException {
List<Issue> listIssues;
if (!LoginUtilities.hasPermission(project, PermissionType.ISSUE_VIEW_ALL)) {
listIssues = new ArrayList<>();
for (Issue issue : is.getIssuesByProjectId(project.getId())) {
if (LoginUtilities.canViewIssue(issue)) {
listIssues.add(issue);
}
}
} else {
listIssues = is.getIssuesByProjectId(project.getId());
}
channel.setDescription(ITrackerResources.getString("itracker.feed.project.description", project.getName()));
channel.setTitle(ITrackerResources.getString("itracker.feed.project.title ", project.getName(), project.getDescription()));
channel.setLink(getProjectURL(project, req, getServletContext(), baseURL));
is.getIssuesByProjectId(project.getId());
List<Item> sItems = projectIssueItems(req, baseURL, listIssues);
channel.setItems(sItems);
}
private void toChannel(Channel channel, Issue issue, String baseURL) throws MalformedURLException {
channel.setDescription( ITrackerResources.getString("itracker.feed.issue.description.description", String.valueOf(issue.getId())));
channel.setTitle(ITrackerResources.getString("itracker.feed.issue.title",
String.valueOf(issue.getId()), issue.getDescription()));
channel.setLink(getIssueURL(issue, baseURL));
channel.setTitle(issue.getId() + " - " + issue.getDescription());
List<Item> sItems = issueHistoryItems(baseURL, issue);
channel.setItems(sItems);
}
private void deny(ServletServerHttpResponse sr) {
sr.getHeaders().clear();
sr.setStatusCode(HttpStatus.FORBIDDEN);
}
private List<Item> projectIssueItems(HttpServletRequest req, String baseURL, List<Issue> listIssues) throws MalformedURLException {
List<Item> sItems = new ArrayList<>(listIssues.size());
final Iterator<Issue> issuesIt = listIssues.iterator();
// start copying from Models to PTOs
Issue issue;
Item current;
while (issuesIt.hasNext()) {
issue = issuesIt.next();
current = new Item();
current.setUri(baseURL + req.getServletPath());
current.setLink(getIssueURL(issue, baseURL));
Guid guid = new Guid();
guid.setValue(current.getLink());
guid.setPermaLink(true);
current.setGuid(guid);
Description desc = new Description();
desc.setType(Content.TEXT);
desc.setValue("Issue " + issue.getId());
current.setDescription(desc);
current.setTitle(issue.getDescription());
current.setPubDate(issue.getLastModifiedDate());
Content c = new Content();
c.setType(Content.HTML);
c.setValue(
issue.getHistory().get(issue.getHistory().size() - 1).getDescription()
);
current.setContent(c);
sItems.add(current);
}
return sItems;
}
private List<Item> issueHistoryItems(String baseURL, Issue i) throws MalformedURLException {
List<Item> sItems = new ArrayList<>(i.getHistory().size());
Item current;
StringBuilder author = new StringBuilder();
List<IssueHistory> history = new LinkedList<>(i.getHistory());
Collections.reverse(history);
for (IssueHistory ih : history) {
int index = ( history.indexOf(ih)+1 );
if (index > 10) {
// limited to newest 10 issues
break;
}
current = new Item();
Content content = new Content();
current.setLink(getIssueURL(i, baseURL));
Guid guid = new Guid();
guid.setValue(current.getLink() + "#h" + index);
guid.setPermaLink(true);
current.setGuid(guid);
current.setTitle(ITrackerResources.getString("itracker.feed.history.title",
String.valueOf(history.size() + 1 - index)));
Description desc = new Description();
desc.setType(Content.TEXT);
desc.setValue(HTMLUtilities.removeMarkup( ih.getDescription() ));
current.setDescription(desc);
content.setType(Content.HTML);
content.setValue(
"<p>" + HTMLUtilities.removeMarkup( ih.getDescription() ) + "</p>"
);
current.setContent(content);
current.setPubDate(ih.getCreateDate());
author.setLength(0);
InternetAddress authorAddress = ih.getUser().getEmailAddress();
if (StringUtils.isNotBlank(authorAddress.getAddress())) {
author.append(authorAddress.getAddress());
if (StringUtils.isNotBlank(authorAddress.getPersonal())) {
author.append(' ')
.append('(')
.append(authorAddress.getPersonal())
.append(')');
}
current.setAuthor(String.valueOf(author));
}
sItems.add(current);
}
return sItems;
}
private String getIssueURL(Issue i, String baseUrl) throws MalformedURLException {
return String.valueOf(IssueUtilities.getIssueURL(i, baseUrl));
}
private String getProjectURL(Project p, HttpServletRequest req, ServletContext context, String baseUrl) {
ModuleConfig conf = ModuleUtils.getInstance().getModuleConfig(
"/module-projects",
req,
context);
ForwardConfig forwardConfig = conf.findForwardConfig("listissues");
return baseUrl + TagUtils.getInstance().pageURL(req, forwardConfig.getPath(), conf) + "?projectId=" + p.getId();
}
}