Skip to content

Commit

Permalink
[JENKINS-60577] - Prevent the RSS feed in Computer page from returnin…
Browse files Browse the repository at this point in the history
…g an error 404 (#4411)

* [JENKINS-60577] Rss Latest Builds for Computer

* [JENKINS-60577] Missing javadoc

* [JENKINS-60577] Add builds from the computer

* Update core/src/main/java/hudson/model/Computer.java

* Apply suggestions from code review

Co-Authored-By: Oleg Nenashev <[email protected]>

* [JENKINS-60577] Document limitation to AbstractProject

* [JENKINS-60577] Restrict the RSS methods in Computer

Co-authored-by: Oleg Nenashev <[email protected]>
  • Loading branch information
fcojfernandez and oleg-nenashev committed Jan 15, 2020
1 parent ec13ac9 commit 3ade716
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 36 deletions.
30 changes: 25 additions & 5 deletions core/src/main/java/hudson/model/Computer.java
Original file line number Diff line number Diff line change
Expand Up @@ -1368,16 +1368,36 @@ public String call() throws IOException {
// UI
//
//
@Restricted(DoNotUse.class)
public void doRssAll( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
rss(req, rsp, " all builds", getBuilds());
RSS.rss(req, rsp, getDisplayName() + " all builds", getUrl(), getBuilds());
}

@Restricted(DoNotUse.class)
public void doRssFailed(StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
rss(req, rsp, " failed builds", getBuilds().failureOnly());
RSS.rss(req, rsp, getDisplayName() + " failed builds", getUrl(), getBuilds().failureOnly());
}
private void rss(StaplerRequest req, StaplerResponse rsp, String suffix, RunList runs) throws IOException, ServletException {
RSS.forwardToRss(getDisplayName() + suffix, getUrl(),
runs.newBuilds(), Run.FEED_ADAPTER, req, rsp);

/**
* Retrieve the RSS feed for the last build for each project executed in this computer.
* Only the information from {@link AbstractProject} is displayed since there isn't a proper API to gather
* information about the node where the builds are executed for other sorts of projects such as Pipeline
* @since TODO
*/
@Restricted(DoNotUse.class)
public void doRssLatest( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
final List<Run> lastBuilds = new ArrayList<>();
for (AbstractProject<?, ?> p : Jenkins.get().allItems(AbstractProject.class)) {
if (p.getLastBuild() != null) {
for (AbstractBuild<?, ?> b = p.getLastBuild(); b != null; b = b.getPreviousBuild()) {
if (b.getBuiltOn() == getNode()) {
lastBuilds.add(b);
break;
}
}
}
}
RSS.rss(req, rsp, getDisplayName() + " last builds only", getUrl(), RunList.fromRuns(lastBuilds));
}

@RequirePOST
Expand Down
10 changes: 2 additions & 8 deletions core/src/main/java/hudson/model/Job.java
Original file line number Diff line number Diff line change
Expand Up @@ -1566,18 +1566,12 @@ protected void checkRename(String newName) throws Failure {

public void doRssAll(StaplerRequest req, StaplerResponse rsp)
throws IOException, ServletException {
rss(req, rsp, " all builds", getBuilds());
RSS.rss(req, rsp, getDisplayName() + " all builds", getUrl(), getBuilds().newBuilds());
}

public void doRssFailed(StaplerRequest req, StaplerResponse rsp)
throws IOException, ServletException {
rss(req, rsp, " failed builds", getBuilds().failureOnly());
}

private void rss(StaplerRequest req, StaplerResponse rsp, String suffix,
RunList runs) throws IOException, ServletException {
RSS.forwardToRss(getDisplayName() + suffix, getUrl(), runs.newBuilds(),
Run.FEED_ADAPTER, req, rsp);
RSS.rss(req, rsp, getDisplayName() + " failed builds", getUrl(), getBuilds().failureOnly().newBuilds());
}

/**
Expand Down
34 changes: 34 additions & 0 deletions core/src/main/java/hudson/model/RSS.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
package hudson.model;

import hudson.FeedAdapter;
import hudson.util.RunList;
import jenkins.model.Jenkins;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
Expand Down Expand Up @@ -90,4 +91,37 @@ public static <E> void forwardToRss(String title, String url, Collection<? exten

req.getView(Jenkins.get(),"/hudson/"+flavor+".jelly").forward(req,rsp);
}

/**
* Sends the RSS feed to the client using a default feed adapter.
*
* @param title
* Title of the feed.
* @param url
* URL of the model object that owns this feed. Relative to the context root.
* @param runList
* Entries to be listed in the RSS feed.
* @since TODO
*/
public static void rss(StaplerRequest req, StaplerResponse rsp, String title, String url, RunList runList) throws IOException, ServletException {
rss(req, rsp, title, url, runList, null);
}

/**
* Sends the RSS feed to the client using a specific feed adapter.
*
* @param title
* Title of the feed.
* @param url
* URL of the model object that owns this feed. Relative to the context root.
* @param runList
* Entries to be listed in the RSS feed.
* @param feedAdapter
* Controls how to render entries to RSS.
* @since TODO
*/
public static void rss(StaplerRequest req, StaplerResponse rsp, String title, String url, RunList runList, FeedAdapter<Run> feedAdapter) throws IOException, ServletException {
final FeedAdapter<Run> feedAdapter_ = feedAdapter == null ? Run.FEED_ADAPTER : feedAdapter;
forwardToRss(title, url, runList, feedAdapter_, req, rsp);
}
}
11 changes: 3 additions & 8 deletions core/src/main/java/hudson/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -872,11 +872,11 @@ public void doDoDelete(StaplerRequest req, StaplerResponse rsp) throws IOExcepti
}

public void doRssAll(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
rss(req, rsp, " all builds", getBuilds(), Run.FEED_ADAPTER);
RSS.rss(req, rsp, getDisplayName() + " all builds", getUrl(), getBuilds().newBuilds());
}

public void doRssFailed(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
rss(req, rsp, " regression builds", getBuilds().regressionOnly(), Run.FEED_ADAPTER);
RSS.rss(req, rsp, getDisplayName() + " regression builds", getUrl(), getBuilds().regressionOnly());
}

public void doRssLatest(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
Expand All @@ -892,12 +892,7 @@ public void doRssLatest(StaplerRequest req, StaplerResponse rsp) throws IOExcept
// historically these have been reported sorted by project name, we switched to the lazy iteration
// so we only have to sort the sublist of runs rather than the full list of irrelevant projects
lastBuilds.sort((o1, o2) -> Items.BY_FULL_NAME.compare(o1.getParent(), o2.getParent()));
rss(req, rsp, " latest build", RunList.fromRuns(lastBuilds), Run.FEED_ADAPTER_LATEST);
}

private void rss(StaplerRequest req, StaplerResponse rsp, String suffix, RunList runs, FeedAdapter adapter)
throws IOException, ServletException {
RSS.forwardToRss(getDisplayName() + suffix, getUrl(), runs.newBuilds(), adapter, req, rsp);
RSS.rss(req, rsp, getDisplayName() + " latest build", getUrl(), RunList.fromRuns(lastBuilds), Run.FEED_ADAPTER_LATEST);
}

@Override
Expand Down
12 changes: 3 additions & 9 deletions core/src/main/java/hudson/model/View.java
Original file line number Diff line number Diff line change
Expand Up @@ -1144,11 +1144,11 @@ public Categories doItemCategories(StaplerRequest req, StaplerResponse rsp, @Que
}

public void doRssAll( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
rss(req, rsp, " all builds", getBuilds());
RSS.rss(req, rsp, getDisplayName() + " all builds", getUrl(), getBuilds().newBuilds());
}

public void doRssFailed( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
rss(req, rsp, " failed builds", getBuilds().failureOnly());
RSS.rss(req, rsp, getDisplayName() + " failed builds", getUrl(), getBuilds().failureOnly().newBuilds());
}

public RunList getBuilds() {
Expand All @@ -1159,11 +1159,6 @@ public BuildTimelineWidget getTimeline() {
return new BuildTimelineWidget(getBuilds());
}

private void rss(StaplerRequest req, StaplerResponse rsp, String suffix, RunList runs) throws IOException, ServletException {
RSS.forwardToRss(getDisplayName()+ suffix, getUrl(),
runs.newBuilds(), Run.FEED_ADAPTER, req, rsp );
}

public void doRssLatest( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
List<Run> lastBuilds = new ArrayList<>();
for (TopLevelItem item : getItems()) {
Expand All @@ -1173,8 +1168,7 @@ public void doRssLatest( StaplerRequest req, StaplerResponse rsp ) throws IOExce
if(lb!=null) lastBuilds.add(lb);
}
}
RSS.forwardToRss(getDisplayName()+" last builds only", getUrl(),
lastBuilds, Run.FEED_ADAPTER_LATEST, req, rsp );
RSS.rss(req, rsp, getDisplayName() + " last builds only", getUrl(), RunList.fromRuns(lastBuilds), Run.FEED_ADAPTER_LATEST);
}

/**
Expand Down
63 changes: 57 additions & 6 deletions test/src/test/java/hudson/model/RSSTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
Expand All @@ -43,7 +47,7 @@ public class RSSTest {
@Test
@Issue("JENKINS-59167")
public void absoluteURLsPresentInRSS_evenWithoutRootUrlSetup() throws Exception {
XmlPage page = getRssPage();
XmlPage page = getRssAllPage();
NodeList allLinks = page.getXmlDocument().getElementsByTagName("link");

assertEquals(1, allLinks.getLength());
Expand All @@ -52,14 +56,14 @@ public void absoluteURLsPresentInRSS_evenWithoutRootUrlSetup() throws Exception
FreeStyleProject p = j.createFreeStyleProject();
j.assertBuildStatusSuccess(p.scheduleBuild2(0));

page = getRssPage();
page = getRssAllPage();
allLinks = page.getXmlDocument().getElementsByTagName("link");

assertEquals(2, allLinks.getLength());
assertAllRSSLinksContainRootUrl(allLinks);
}

private XmlPage getRssPage() throws Exception {
private XmlPage getRssAllPage() throws Exception {
return (XmlPage) j.createWebClient().goTo("rssAll?flavor=rss20", "text/xml");
}

Expand All @@ -74,7 +78,7 @@ private void assertAllRSSLinksContainRootUrl(NodeList allLinks) throws Exception
@Test
@Issue("JENKINS-59167")
public void absoluteURLsPresentInAtom_evenWithoutRootUrlSetup() throws Exception {
XmlPage page = getAtomPage();
XmlPage page = getRssAllAtomPage();
NodeList allLinks = page.getXmlDocument().getElementsByTagName("link");

assertEquals(1, allLinks.getLength());
Expand All @@ -83,14 +87,14 @@ public void absoluteURLsPresentInAtom_evenWithoutRootUrlSetup() throws Exception
FreeStyleProject p = j.createFreeStyleProject();
j.assertBuildStatusSuccess(p.scheduleBuild2(0));

page = getAtomPage();
page = getRssAllAtomPage();
allLinks = page.getXmlDocument().getElementsByTagName("link");

assertEquals(2, allLinks.getLength());
assertAllAtomLinksContainRootUrl(allLinks);
}

private XmlPage getAtomPage() throws Exception {
private XmlPage getRssAllAtomPage() throws Exception {
return (XmlPage) j.createWebClient().goTo("rssAll", "application/atom+xml");
}

Expand All @@ -102,4 +106,51 @@ private void assertAllAtomLinksContainRootUrl(NodeList allLinks) throws Exceptio
assertThat(url, containsString(j.getURL().toString()));
}
}

@Issue("JENKINS-60577")
@Test
public void latestBuilds() throws Exception {
XmlPage page = getRssLatestPage();
NodeList allLinks = page.getXmlDocument().getElementsByTagName("link");

assertEquals(1, allLinks.getLength());

FreeStyleProject p = j.createFreeStyleProject("test1");
j.assertBuildStatusSuccess(p.scheduleBuild2(0));
j.assertBuildStatusSuccess(p.scheduleBuild2(0));

p = j.createFreeStyleProject("test2");
j.assertBuildStatusSuccess(p.scheduleBuild2(0));
j.assertBuildStatusSuccess(p.scheduleBuild2(0));
j.assertBuildStatusSuccess(p.scheduleBuild2(0));

page = getRssLatestPage();
allLinks = page.getXmlDocument().getElementsByTagName("link");

assertEquals(3, allLinks.getLength());
assertLatestRSSLinks(allLinks);

page = getRssAllPage();
allLinks = page.getXmlDocument().getElementsByTagName("link");
assertEquals(6, allLinks.getLength());
}

private XmlPage getRssLatestPage() throws Exception {
return (XmlPage) j.createWebClient().goTo("rssLatest?flavor=rss20", "text/xml");
}

private void assertLatestRSSLinks(NodeList allLinks) throws Exception {
List<String> urls = new ArrayList<>(allLinks.getLength());
for (int i = 0; i < allLinks.getLength(); i++) {
Node item = allLinks.item(i);
String url = item.getTextContent();
urls.add(url);
}

assertThat(urls, containsInAnyOrder(
j.getURL().toString(),
j.getURL().toString() + "job/test1/2/",
j.getURL().toString() + "job/test2/3/"
));
}
}

0 comments on commit 3ade716

Please sign in to comment.