Skip to content

Commit

Permalink
checkpoint. do not commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
terabyte committed Oct 22, 2015
1 parent b81a475 commit 213bb62
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 26 deletions.
67 changes: 56 additions & 11 deletions src/main/java/com/offbytwo/jenkins/JenkinsServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,28 @@

package com.offbytwo.jenkins;

import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBException;

import org.apache.http.client.HttpResponseException;
import org.apache.http.entity.ContentType;
import org.assertj.core.util.Lists;
import org.dom4j.DocumentException;

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.util.EncodingUtils;
import com.offbytwo.jenkins.model.Build;
import com.offbytwo.jenkins.model.Computer;
import com.offbytwo.jenkins.model.ComputerSet;
import com.offbytwo.jenkins.model.FolderJob;
import com.offbytwo.jenkins.model.Job;
import com.offbytwo.jenkins.model.JobConfiguration;
import com.offbytwo.jenkins.model.JobWithDetails;
Expand All @@ -23,17 +38,6 @@
import com.offbytwo.jenkins.model.QueueReference;
import com.offbytwo.jenkins.model.View;

import org.apache.http.client.HttpResponseException;
import org.apache.http.entity.ContentType;
import org.dom4j.DocumentException;

import javax.xml.bind.JAXBException;

import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;

/**
* The main starting point for interacting with a Jenkins server.
*/
Expand Down Expand Up @@ -189,6 +193,23 @@ public MavenJobWithDetails getMavenJob(String jobName) throws IOException {
}
}

public Optional<FolderJob> getFolderJob(Job job) throws IOException {
try {
FolderJob folder = client.get(job.getUrl(), FolderJob.class);
if (!folder.isFolder()) {
return Optional.absent();
}
folder.setClient(client);

return Optional.of(folder);
} catch (HttpResponseException e) {
if (e.getStatusCode() == 404) {
return null;
}
throw e;
}
}

/**
* Create a job on the server using the provided xml
*
Expand All @@ -203,6 +224,30 @@ public void createJob(String jobName, String jobXml, Boolean crumbFlag) throws I
client.post_xml("/createItem?name=" + EncodingUtils.encodeParam(jobName), jobXml, crumbFlag);
}

/**
* Create a folder on the server (in the root)
*
* @throws IOException
*/
public void createFolder(String jobName) throws IOException {
createFolder(jobName, false);
}

/**
* Create a folder on the server (in the root)
*
* @throws IOException
*/
public void createFolder(String jobName, Boolean crumbFlag) throws IOException {
// https://gist.github.com/stuart-warren/7786892 was slightly helpful here
ImmutableMap<String, String> params = ImmutableMap.of(
"mode", "com.cloudbees.hudson.plugins.folder.Folder",
"name", EncodingUtils.encodeParam(jobName),
"from", "",
"Submit", "OK");
client.post_form("/createItem?", params, crumbFlag);
}

/**
* Get the xml description of an existing job
*
Expand Down
92 changes: 77 additions & 15 deletions src/main/java/com/offbytwo/jenkins/client/JenkinsHttpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@

package com.offbytwo.jenkins.client;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.offbytwo.jenkins.client.util.RequestReleasingInputStream;
//import com.offbytwo.jenkins.client.util.HttpResponseContentExtractor;
import com.offbytwo.jenkins.client.validator.HttpResponseValidator;
import com.offbytwo.jenkins.model.BaseModel;
import com.offbytwo.jenkins.model.Crumb;
import com.offbytwo.jenkins.model.ExtractHeader;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
import static org.apache.commons.lang.StringUtils.isNotBlank;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
Expand All @@ -28,20 +30,25 @@
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;
import org.jsoup.helper.StringUtil;
import org.mortbay.util.ajax.JSON;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.io.ByteStreams;
import com.offbytwo.jenkins.client.util.EncodingUtils;
import com.offbytwo.jenkins.client.util.RequestReleasingInputStream;
//import com.offbytwo.jenkins.client.util.HttpResponseContentExtractor;
import com.offbytwo.jenkins.client.validator.HttpResponseValidator;
import com.offbytwo.jenkins.model.BaseModel;
import com.offbytwo.jenkins.model.Crumb;
import com.offbytwo.jenkins.model.ExtractHeader;

public class JenkinsHttpClient {

Expand Down Expand Up @@ -231,6 +238,47 @@ public <R extends BaseModel, D> R post(String path, D data, Class<R> cls, boolea
}
}

/**
* Perform a POST request using form url encoding
*
* @param path path to request, can be relative or absolute
* @param data data to post
* @throws IOException, HttpResponseException
*/
public void post_form(String path, Map<String,String> data, boolean crumbFlag) throws IOException {
HttpPost request;
if (data != null) {
// https://gist.github.com/stuart-warren/7786892 was slightly helpful here
List<String> queryParams = Lists.newArrayList();
for (String param : data.keySet()) {
queryParams.add(param + "=" + EncodingUtils.encodeParam(data.get(param)));
}
queryParams.add("json=" + EncodingUtils.encodeParam(JSON.toString(data)));
String value = mapper.writeValueAsString(data);
StringEntity stringEntity = new StringEntity(value, ContentType.APPLICATION_FORM_URLENCODED);
request = new HttpPost(noapi(path) + StringUtil.join(queryParams, "&"));
request.setEntity(stringEntity);
} else {
request = new HttpPost(noapi(path));
}

if (crumbFlag == true) {
Crumb crumb = get("/crumbIssuer", Crumb.class);
if (crumb != null) {
request.addHeader(new BasicHeader(crumb.getCrumbRequestField(), crumb.getCrumb()));
}
}

HttpResponse response = client.execute(request, localContext);

try {
httpResponseValidator.validateResponse(response);
} finally {
EntityUtils.consume(response.getEntity());
releaseConnection(request);
}
}

/**
* Perform a POST request of XML (instead of using json mapper) and return a string rendering of the response
* entity.
Expand Down Expand Up @@ -336,6 +384,9 @@ private String urlJoin(String path1, String path2) {
}

private URI api(String path) {
if (path.contains("createItem")) {
return uri.resolve("/").resolve(path);
}
if (!path.toLowerCase().matches("https?://.*")) {
path = urlJoin(this.context, path);
}
Expand All @@ -348,9 +399,20 @@ private URI api(String path) {
return uri.resolve("/").resolve(path);
}

private URI noapi(String path) {
if (!path.toLowerCase().matches("https?://.*")) {
path = urlJoin(this.context, path);
}
return uri.resolve("/").resolve(path);
}

private <T extends BaseModel> T objectFromResponse(Class<T> cls, HttpResponse response) throws IOException {
InputStream content = response.getEntity().getContent();
T result = mapper.readValue(content, cls);
byte[] bytes = ByteStreams.toByteArray(content);
String bytestring = new String(bytes);
T result = mapper.readValue(bytes, cls);
// TODO: original:
//T result = mapper.readValue(content, cls);
result.setClient(this);
return result;
}
Expand Down
62 changes: 62 additions & 0 deletions src/main/java/com/offbytwo/jenkins/model/FolderJob.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.offbytwo.jenkins.model;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.google.common.base.Function;
import com.google.common.collect.Maps;

public class FolderJob extends Job {

String displayName;
List<Job> jobs;

public FolderJob() {}

public String getDisplayName() {
return displayName;
}

/**
* Determine if this FolderJob object is a valid folder or not.
*
* (internally: if jobs list exists)
*
* @return true if this job is a folder.
*/
public boolean isFolder() {
if (jobs != null) {
return true;
}
return false;
}

/**
* Get a list of all the defined jobs in this folder
*
* @return list of defined jobs (summary level, for details @see Job#details
* @throws IOException
*/
public Map<String, Job> getJobs() {
return Maps.uniqueIndex(jobs, new Function<Job, String>() {
@Override
public String apply(Job job) {
job.setClient(client);
return job.getName().toLowerCase();
}
});
}

/* TODO
public List<Job> getJobsRecursive() {
return Lists.transform(jobs, new Function<Job, Job>() {
@Override
public Job apply(Job job) {
// TODO: try to see if each job is a folder
return job;
}
});
}
*/
}
39 changes: 39 additions & 0 deletions src/test/java/Testz.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import java.net.URI;
import java.util.Map;

import org.junit.Test;

import com.google.common.base.Optional;
import com.offbytwo.jenkins.JenkinsServer;
import com.offbytwo.jenkins.model.FolderJob;
import com.offbytwo.jenkins.model.Job;



public class Testz {

@Test
public void testStuff() {
try {
JenkinsServer test = new JenkinsServer(new URI("http://localhost:8080/"));
Map<String, Job> jobs = test.getJobs();
for (String s : jobs.keySet()) {
System.out.println("Job " + s + " is at " + jobs.get(s).getUrl());
}
Job job = jobs.get("test folder");

Optional<FolderJob> ofj = test.getFolderJob(job);
FolderJob fj = ofj.get();

Map<String, Job> moarJobs = fj.getJobs();
for (String s : moarJobs.keySet()) {
System.out.println("Job " + s + " is at " + moarJobs.get(s).getUrl());
}

System.out.println("test: " + fj.toString());
test.createFolder("testzzz");
} catch (Exception e) {
e.printStackTrace();
}
}
}

0 comments on commit 213bb62

Please sign in to comment.