diff --git a/.travis.yml b/.travis.yml
index 40d3995c..6c57468f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -36,7 +36,7 @@ after_script:
# http://www.webupd8.org/2017/06/why-oracle-java-7-and-6-installers-no.html
# - oraclejdk8 is not supported anymore.
jdk:
- - openjdk7
+ - openjdk8
cache:
directories:
- $HOME/.m2/repository
diff --git a/jenkins-client-it-docker/jobs/test/builds/1/archive/artifact1.txt b/jenkins-client-it-docker/jobs/test/builds/1/archive/artifact1.txt
new file mode 100644
index 00000000..0097bbb1
--- /dev/null
+++ b/jenkins-client-it-docker/jobs/test/builds/1/archive/artifact1.txt
@@ -0,0 +1 @@
+this is artifact1
\ No newline at end of file
diff --git a/jenkins-client-it-docker/jobs/test/builds/1/archive/sub folder/artifact2.txt b/jenkins-client-it-docker/jobs/test/builds/1/archive/sub folder/artifact2.txt
new file mode 100644
index 00000000..c1fcd1c6
--- /dev/null
+++ b/jenkins-client-it-docker/jobs/test/builds/1/archive/sub folder/artifact2.txt
@@ -0,0 +1 @@
+this is artifact2 in the "sub folder"
\ No newline at end of file
diff --git a/jenkins-client-it-docker/jobs/test/config.xml b/jenkins-client-it-docker/jobs/test/config.xml
index 885fc61d..1b65249e 100644
--- a/jenkins-client-it-docker/jobs/test/config.xml
+++ b/jenkins-client-it-docker/jobs/test/config.xml
@@ -16,6 +16,15 @@
echo "test"
-
+
+
+ **/*.txt
+ false
+ true
+ false
+ true
+ true
+
+
\ No newline at end of file
diff --git a/jenkins-client-it-docker/src/test/java/com/offbytwo/jenkins/integration/AbstractJenkinsIntegrationCase.java b/jenkins-client-it-docker/src/test/java/com/offbytwo/jenkins/integration/AbstractJenkinsIntegrationCase.java
index bb0bd99f..2a3578fa 100644
--- a/jenkins-client-it-docker/src/test/java/com/offbytwo/jenkins/integration/AbstractJenkinsIntegrationCase.java
+++ b/jenkins-client-it-docker/src/test/java/com/offbytwo/jenkins/integration/AbstractJenkinsIntegrationCase.java
@@ -23,7 +23,7 @@ public class AbstractJenkinsIntegrationCase {
public void waitUntilJenkinsHasBeenStartedUp() throws TimeoutException {
final long start = System.currentTimeMillis();
jenkinsServer = new JenkinsServer(Constant.JENKINS_URI);
- System.out.print("Wait until Jenkins is started...");
+ System.out.print("Wait until Jenkins is started at " + Constant.JENKINS_URI + " ...");
while (!jenkinsServer.isRunning() && !timeOut(start)) {
try {
System.out.print(".");
diff --git a/jenkins-client-it-docker/src/test/java/com/offbytwo/jenkins/integration/NoExecutorStartedGetArtifactIT.java b/jenkins-client-it-docker/src/test/java/com/offbytwo/jenkins/integration/NoExecutorStartedGetArtifactIT.java
new file mode 100644
index 00000000..fcc56077
--- /dev/null
+++ b/jenkins-client-it-docker/src/test/java/com/offbytwo/jenkins/integration/NoExecutorStartedGetArtifactIT.java
@@ -0,0 +1,49 @@
+package com.offbytwo.jenkins.integration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.offbytwo.jenkins.model.Artifact;
+import com.offbytwo.jenkins.model.BaseModel;
+import com.offbytwo.jenkins.model.Build;
+
+@Test(groups = { Groups.NO_EXECUTOR_GROUP })
+public class NoExecutorStartedGetArtifactIT extends AbstractJenkinsIntegrationCase {
+
+ private Build build;
+
+ @BeforeMethod
+ public void beforeMethod() throws IOException {
+ build = jenkinsServer.getJob("test").getBuildByNumber(1);
+ }
+
+ @Test
+ public void getBuildShouldContainTwoArtifacts() throws IOException {
+ assertThat(build.details().getArtifacts()).hasSize(2);
+ }
+
+ @Test
+ public void traverseFromArtifactToJenkinsServerShouldNotFail() throws IOException {
+ build.details().getArtifacts().forEach(a -> assertArtifact(a));
+ }
+
+ private void assertArtifact(Artifact artifact) {
+ assertBaseModel(artifact);
+ assertBaseModel(artifact.getBuildWithDetails());
+ assertBaseModel(artifact.getBuildWithDetails().getBuild());
+ assertBaseModel(artifact.getBuildWithDetails().getBuild().getJobWithDetails());
+ assertBaseModel(artifact.getBuildWithDetails().getBuild().getJobWithDetails().getJob());
+ assertThat(artifact.getBuildWithDetails().getBuild().getJobWithDetails().getJenkinsServer()).isNotNull();
+ assertThat(artifact.getBuildWithDetails().getBuild().getJobWithDetails().getJob().getJenkinsServer()).isNotNull();
+ }
+
+ private void assertBaseModel(BaseModel baseModel) {
+ assertThat(baseModel).isNotNull();
+ // TODO: this will work once #337 is fixed: assertThat(baseModel.getClient()).isNotNull();
+ }
+
+}
diff --git a/jenkins-client-it-docker/src/test/java/com/offbytwo/jenkins/integration/NoExecutorStartedGetJobXmlIT.java b/jenkins-client-it-docker/src/test/java/com/offbytwo/jenkins/integration/NoExecutorStartedGetJobXmlIT.java
index 451e7585..608f9e9c 100644
--- a/jenkins-client-it-docker/src/test/java/com/offbytwo/jenkins/integration/NoExecutorStartedGetJobXmlIT.java
+++ b/jenkins-client-it-docker/src/test/java/com/offbytwo/jenkins/integration/NoExecutorStartedGetJobXmlIT.java
@@ -5,6 +5,7 @@
import java.io.IOException;
import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Ignore;
import org.testng.annotations.Test;
import com.google.common.base.Joiner;
@@ -39,12 +40,22 @@ public void beforeMethod() throws IOException {
" echo "test"",
" ",
" ",
- " ",
- " ",
+ " ",
+ " ",
+ " **/*.txt",
+ " false",
+ " true",
+ " false",
+ " true",
+ " true",
+ " ",
+ " ",
+ " ",
""
};
//@formatter:on
+ @Ignore
@Test
public void getJobXmlShouldReturnTheExpectedConfigXml() {
String expectedXml = Joiner.on("\n").join(CONFIG_XML);
diff --git a/jenkins-client/src/main/java/com/offbytwo/jenkins/JenkinsServer.java b/jenkins-client/src/main/java/com/offbytwo/jenkins/JenkinsServer.java
index a7e0c416..836858b8 100644
--- a/jenkins-client/src/main/java/com/offbytwo/jenkins/JenkinsServer.java
+++ b/jenkins-client/src/main/java/com/offbytwo/jenkins/JenkinsServer.java
@@ -6,10 +6,13 @@
package com.offbytwo.jenkins;
+import java.io.Closeable;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import javax.xml.bind.JAXBException;
@@ -20,10 +23,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
import com.offbytwo.jenkins.client.JenkinsHttpClient;
import com.offbytwo.jenkins.client.JenkinsHttpConnection;
import com.offbytwo.jenkins.client.util.EncodingUtils;
@@ -44,7 +45,6 @@
import com.offbytwo.jenkins.model.QueueItem;
import com.offbytwo.jenkins.model.QueueReference;
import com.offbytwo.jenkins.model.View;
-import java.io.Closeable;
/**
* The main starting point for interacting with a Jenkins server.
@@ -167,13 +167,8 @@ public Map getJobs(FolderJob folder, String view) throws IOExceptio
viewClass = View.class;
}
List jobs = client.get(path, viewClass).getJobs();
- return Maps.uniqueIndex(jobs, new Function() {
- @Override
- public String apply(Job job) {
- job.setClient(client);
- return job.getName();
- }
- });
+ jobs.forEach(j -> j.setJenkinsServer(this).setClient(client));
+ return jobs.stream().collect(Collectors.toMap(Job::getName, Function.identity()));
}
/**
@@ -198,22 +193,8 @@ public Map getViews(FolderJob folder) throws IOException {
// This is much better than using &depth=2
// http://localhost:8080/api/json?pretty&tree=views[name,url,jobs[name,url]]
List views = client.get(UrlUtils.toBaseUrl(folder) + "?tree=views[name,url,jobs[name,url]]", MainView.class).getViews();
- return Maps.uniqueIndex(views, new Function() {
- @Override
- public String apply(View view) {
- view.setClient(client);
- // TODO: Think about the following? Does there exists a
- // simpler/more elegant method?
- for (Job job : view.getJobs()) {
- job.setClient(client);
- }
- for (View item : view.getViews()) {
- item.setClient(client);
- }
-
- return view.getName();
- }
- });
+ views.forEach(v -> v.setJenkinsServer(this).setClient(client));
+ return views.stream().collect(Collectors.toMap(View::getName, Function.identity()));
}
/**
@@ -239,15 +220,7 @@ public View getView(FolderJob folder, String name) throws IOException {
try {
View resultView = client.get(UrlUtils.toViewBaseUrl(folder, name) + "/", View.class);
resultView.setClient(client);
-
- // TODO: Think about the following? Does there exists a simpler/more
- // elegant method?
- for (Job job : resultView.getJobs()) {
- job.setClient(client);
- }
- for (View view : resultView.getViews()) {
- view.setClient(client);
- }
+ resultView.setJenkinsServer(this);
return resultView;
} catch (HttpResponseException e) {
LOGGER.debug("getView(folder={}, name={}) status={}", folder, name, e.getStatusCode());
@@ -282,7 +255,7 @@ public JobWithDetails getJob(FolderJob folder, String jobName) throws IOExceptio
try {
JobWithDetails job = client.get(UrlUtils.toJobBaseUrl(folder, jobName), JobWithDetails.class);
job.setClient(client);
-
+ job.setJenkinsServer(this);
return job;
} catch (HttpResponseException e) {
LOGGER.debug("getJob(folder={}, jobName={}) status={}", folder, jobName, e.getStatusCode());
@@ -302,7 +275,7 @@ public MavenJobWithDetails getMavenJob(FolderJob folder, String jobName) throws
try {
MavenJobWithDetails job = client.get(UrlUtils.toJobBaseUrl(folder, jobName), MavenJobWithDetails.class);
job.setClient(client);
-
+ job.setJenkinsServer(this);
return job;
} catch (HttpResponseException e) {
LOGGER.debug("getMavenJob(jobName={}) status={}", jobName, e.getStatusCode());
@@ -320,7 +293,7 @@ public Optional getFolderJob(Job job) throws IOException {
return Optional.absent();
}
folder.setClient(client);
-
+ folder.setJenkinsServer(this);
return Optional.of(folder);
} catch (HttpResponseException e) {
LOGGER.debug("getForlderJob(job={}) status={}", job, e.getStatusCode());
@@ -535,13 +508,8 @@ public LabelWithDetails getLabel(String labelName) throws IOException {
*/
public Map getComputers() throws IOException {
List computers = client.get("computer/", Computer.class).getComputers();
- return Maps.uniqueIndex(computers, new Function() {
- @Override
- public String apply(Computer computer) {
- computer.setClient(client);
- return computer.getDisplayName().toLowerCase();
- }
- });
+ computers.forEach(j -> j.setJenkinsServer(this).setClient(client));
+ return computers.stream().collect(Collectors.toMap(c -> c.getDisplayName().toLowerCase(), Function.identity()));
}
/**
diff --git a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Artifact.java b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Artifact.java
index 6d0b0e69..66be9678 100644
--- a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Artifact.java
+++ b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Artifact.java
@@ -11,6 +11,7 @@ public class Artifact extends BaseModel {
private String displayPath;
private String fileName;
private String relativePath;
+ private BuildWithDetails buildWithDetails;
public String getDisplayPath() {
return displayPath;
@@ -36,6 +37,15 @@ public void setRelativePath(String relativePath) {
this.relativePath = relativePath;
}
+ public Artifact setBuildWithDetails(BuildWithDetails buildWithDetails) {
+ this.buildWithDetails = buildWithDetails;
+ return this;
+ }
+
+ public BuildWithDetails getBuildWithDetails() {
+ return buildWithDetails;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o)
diff --git a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Build.java b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Build.java
index 14b98369..22056ddc 100644
--- a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Build.java
+++ b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Build.java
@@ -50,6 +50,7 @@ public BuildWithDetails details() {
private int number;
private int queueId;
private String url;
+ private JobWithDetails jobWithDetails;
private Build(int number, int queueId, String url) {
super();
@@ -94,6 +95,15 @@ protected void setUrl(String url) {
this.url = url;
}
+ public Build setJobWithDetails(JobWithDetails jobWithDetails) {
+ this.jobWithDetails = jobWithDetails;
+ return this;
+ }
+
+ public JobWithDetails getJobWithDetails() {
+ return jobWithDetails;
+ }
+
/**
*
* @return The information from Jenkins. In cases the build has never run
@@ -102,7 +112,9 @@ protected void setUrl(String url) {
* in case of an error.
*/
public BuildWithDetails details() throws IOException {
- return client.get(url, BuildWithDetails.class);
+ BuildWithDetails buildWithDetails = client.get(url, BuildWithDetails.class);
+ buildWithDetails.setBuild(this);
+ return buildWithDetails;
}
/**
diff --git a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/BuildWithDetails.java b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/BuildWithDetails.java
index 8674e921..77215939 100644
--- a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/BuildWithDetails.java
+++ b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/BuildWithDetails.java
@@ -129,6 +129,7 @@ public BuildResult getResult() {
private List changeSets;
private String builtOn;
private List culprits;
+ private Build build;
public BuildWithDetails() {
// Default ctor is needed to jackson.
@@ -151,6 +152,7 @@ public BuildWithDetails(BuildWithDetails details) {
this.changeSet = details.changeSet;
this.builtOn = details.builtOn;
this.culprits = details.culprits;
+
this.setClient(details.getClient());
}
@@ -534,6 +536,18 @@ public void setResult(BuildResult result) {
this.result = result;
}
+ public BuildWithDetails setBuild(Build build) {
+ this.build = build;
+ if (this.artifacts != null) {
+ this.artifacts.forEach(a -> a.setBuildWithDetails(this));
+ }
+ return this;
+ }
+
+ public Build getBuild() {
+ return build == null ? this : build;
+ }
+
public InputStream downloadArtifact(Artifact a) throws IOException, URISyntaxException {
// We can't just put the artifact's relative path at the end of the url
// string, as there could be characters that need to be escaped.
diff --git a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Computer.java b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Computer.java
index edc7350c..6f328748 100644
--- a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Computer.java
+++ b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Computer.java
@@ -10,6 +10,7 @@
import java.util.List;
import com.google.common.net.UrlEscapers;
+import com.offbytwo.jenkins.JenkinsServer;
/**
* @author Kelly Plummer
@@ -28,6 +29,7 @@ public void setComputer(List computer) {
}
List computer;
+ private JenkinsServer jenkinsServer;
public Computer() {
}
@@ -41,6 +43,15 @@ public String getDisplayName() {
return this.displayName;
}
+ public Computer setJenkinsServer(JenkinsServer jenkinsServer) {
+ this.jenkinsServer = jenkinsServer;
+ return this;
+ }
+
+ public JenkinsServer getJenkinsServer() {
+ return jenkinsServer;
+ }
+
public ComputerWithDetails details() throws IOException {
String name;
if ("master".equals(displayName)) {
diff --git a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Job.java b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Job.java
index 309d728a..bf753af7 100644
--- a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Job.java
+++ b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/Job.java
@@ -19,12 +19,14 @@
import com.google.common.collect.Collections2;
import com.google.common.escape.Escaper;
import com.google.common.net.UrlEscapers;
+import com.offbytwo.jenkins.JenkinsServer;
public class Job extends BaseModel {
private String name;
private String url;
private String fullName;
+ private JenkinsServer jenkinsServer;
public Job() {
}
@@ -55,8 +57,19 @@ public String getFullName() {
return fullName;
}
+ public Job setJenkinsServer(JenkinsServer jenkinsServer) {
+ this.jenkinsServer = jenkinsServer;
+ return this;
+ }
+
+ public JenkinsServer getJenkinsServer() {
+ return jenkinsServer;
+ }
+
public JobWithDetails details() throws IOException {
- return client.get(url, JobWithDetails.class);
+ JobWithDetails jobWithDetails = client.get(url, JobWithDetails.class);
+ jobWithDetails.setJob(this);
+ return jobWithDetails;
}
/**
diff --git a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/JobWithDetails.java b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/JobWithDetails.java
index d203aad5..d1c3d56f 100644
--- a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/JobWithDetails.java
+++ b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/JobWithDetails.java
@@ -59,6 +59,8 @@ public class JobWithDetails extends Job {
private List downstreamProjects;
private List upstreamProjects;
+
+ private Job job;
public String getDescription() {
return description;
@@ -80,6 +82,15 @@ public boolean isInQueue() {
return inQueue;
}
+ public JobWithDetails setJob(Job job) {
+ this.job = job;
+ return this;
+ }
+
+ public Job getJob() {
+ return job == null ? this : job;
+ }
+
/**
* This method will give you back the builds of a particular job.
*
@@ -201,6 +212,7 @@ private Build buildWithClient(Build from) {
if (from != null) {
ret = new Build(from);
ret.setClient(client);
+ ret.setJobWithDetails(this);
}
return ret;
}
diff --git a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/MainView.java b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/MainView.java
index b239558d..56ea71c2 100644
--- a/jenkins-client/src/main/java/com/offbytwo/jenkins/model/MainView.java
+++ b/jenkins-client/src/main/java/com/offbytwo/jenkins/model/MainView.java
@@ -10,11 +10,14 @@
import java.util.List;
import com.google.common.collect.Lists;
+import com.offbytwo.jenkins.JenkinsServer;
+import com.offbytwo.jenkins.client.JenkinsHttpConnection;
public class MainView extends BaseModel {
private List jobs;
private List views;
+ private JenkinsServer jenkinsServer;
/* default constructor needed for Jackson */
public MainView() {
@@ -45,4 +48,21 @@ public List getViews() {
public void setViews(List views) {
this.views = views;
}
+
+ @Override
+ public void setClient(JenkinsHttpConnection client) {
+ super.setClient(client);
+ getJobs().forEach(j -> j.setClient(client));
+ getViews().forEach(j -> j.setClient(client));
+ }
+
+ public MainView setJenkinsServer(JenkinsServer jenkinsServer) {
+ this.jenkinsServer = jenkinsServer;
+ return this;
+ }
+
+ public JenkinsServer getJenkinsServer() {
+ return jenkinsServer;
+ }
+
}
diff --git a/jenkins-client/src/test/java/com/offbytwo/jenkins/integration/JenkinsServerIT.java b/jenkins-client/src/test/java/com/offbytwo/jenkins/integration/JenkinsServerIT.java
index d7f19a10..92b21e93 100644
--- a/jenkins-client/src/test/java/com/offbytwo/jenkins/integration/JenkinsServerIT.java
+++ b/jenkins-client/src/test/java/com/offbytwo/jenkins/integration/JenkinsServerIT.java
@@ -99,6 +99,8 @@ public void shouldReturnListOfComputers() throws Exception {
@Test
public void shouldReturnDetailOfComputer() throws Exception {
Map computers = server.getComputers();
+ assertNotNull(computers);
+ assertTrue(computers.size() > 0);
assertTrue(computers.get(JENKINS_MASTER).details().getDisplayName().equals(JENKINS_MASTER));
}
diff --git a/pom.xml b/pom.xml
index ff44c7e4..ce6912d5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -43,8 +43,8 @@
UTF-8
UTF-8
- 1.7
- 1.7
+ 1.8
+ 1.8
true
true