com.serena.rlc.provider.jenkins.client.JenkinsClient.java Source code

Java tutorial

Introduction

Here is the source code for com.serena.rlc.provider.jenkins.client.JenkinsClient.java

Source

/*
 *
 * Copyright (c) 2015 SERENA Software, Inc. All Rights Reserved.
 *
 * This software is proprietary information of SERENA Software, Inc.
 * Use is subject to license terms.
 *
 */

package com.serena.rlc.provider.jenkins.client;

import com.serena.rlc.provider.jenkins.domain.BuildInfo;
import com.serena.rlc.provider.jenkins.domain.Job;
import com.serena.rlc.provider.jenkins.exception.JenkinsClientException;

import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.*;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.DefaultHttpClient;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.entity.UrlEncodedFormEntity;

import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

/**
 * @author rcook
 */

@Component
public class JenkinsClient {
    private static final Logger logger = LoggerFactory.getLogger(JenkinsClient.class);

    public static String DEFAULT_HTTP_CONTENT_TYPE = "application/json";

    private String jenkinsUrl;
    private String jenkinsUsername;
    private String jenkinsPassword;
    private int pollSleepTime = 1000;
    private int maxPollCount = 15;

    public JenkinsClient() {

    }

    public JenkinsClient(String url) {
        this.jenkinsUrl = url;
    }

    public JenkinsClient(String url, String username, String password) {
        this.jenkinsUrl = url;
        this.jenkinsUsername = username;
        this.jenkinsPassword = password;
    }

    public String getJenkinsUrl() {
        return jenkinsUrl;
    }

    public void setJenkinsUrl(String url) {
        this.jenkinsUrl = url;
    }

    public String getJenkinsUsername() {
        return jenkinsUsername;
    }

    public void setJenkinsUsername(String username) {
        this.jenkinsUsername = username;
    }

    public String getJenkinsPassword() {
        return jenkinsPassword;
    }

    public void setJenkinsPassword(String password) {
        this.jenkinsPassword = password;
    }

    public int getPollSleepTime() {
        return pollSleepTime;
    }

    public void setPollSleepTime(int pollSleepTime) {
        this.pollSleepTime = pollSleepTime;
    }

    public int getMaxPollCount() {
        return maxPollCount;
    }

    public void setMaxPollCount(int maxPollCount) {
        this.maxPollCount = maxPollCount;
    }

    public void createConnection(String url, String username, String password) {
        this.jenkinsUrl = url;
        this.jenkinsUsername = username;
        this.jenkinsPassword = password;
    }

    public void createConnection(String url) {
        this.jenkinsUrl = url;
    }

    public List<Job> getJobs() throws JenkinsClientException {
        logger.debug("Using Jenkins URL: " + getJenkinsUrl());
        logger.debug("Retrieving Jenkins Jobs");

        String jobsResponse = processGet(getJenkinsUrl(), "api/json?tree=jobs[name,displayName]");
        logger.debug(jobsResponse);

        List<Job> jobs = Job.parse(jobsResponse);
        return jobs;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Send a POST and returns the Location header which contains the url to the queued item
     *
     * @param jenkinsUrl
     * @param postPath
     * @param postData
     * @return Response body
     * @throws JenkinsClientException
     */
    public String processBuildPost(String jenkinsUrl, String postPath, String postData)
            throws JenkinsClientException {
        String uri = createUrl(jenkinsUrl, postPath);

        logger.debug("Start executing Jenkins POST request to url=\"{}\" with payload={}", uri);

        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost postRequest = new HttpPost(uri);

        if (getJenkinsUsername() != null && !StringUtils.isEmpty(getJenkinsUsername())) {
            UsernamePasswordCredentials creds = new UsernamePasswordCredentials(getJenkinsUsername(),
                    getJenkinsPassword());
            postRequest.addHeader(BasicScheme.authenticate(creds, "US-ASCII", false));
        }

        postRequest.addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
        postRequest.addHeader(HttpHeaders.ACCEPT, "application/json");
        String result = "";

        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("json", postData));

        try {

            postRequest.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));

            HttpResponse response = httpClient.execute(postRequest);
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK
                    && response.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED) {
                throw createHttpError(response);
            }

            result = response.getFirstHeader("Location").getValue();

            logger.debug("End executing Jenkins POST request to url=\"{}\" and receive this result={}", uri,
                    result);

        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            throw new JenkinsClientException("Server not available", e);
        } finally {
            httpClient.getConnectionManager().shutdown();
        }

        return result;
    }

    public BuildInfo startBuild(String jobName, String parameters) throws JenkinsClientException {
        logger.debug("Start Jenkins Job \"{}\" with parameters: {}", jobName, parameters);

        //String queueLocation = processBuildPost(this.getJenkinsUrl(), "job/" + jobName + "/build", parameters);
        String queueLocation = this.processBuildPost(this.getJenkinsUrl(),
                "job/" + jobName + "/buildWithParameters" + parameters, null);

        BuildInfo queueCheckResult = null;
        logger.debug("Checking Queue Location ({})", queueLocation);

        // Jenkins does not return a build number when a build is started. It returns a URL to the build queue
        // which is not available immediately. Once it is available and the time 
        int pollCount = 0;

        while (pollCount < getMaxPollCount()) {
            try {
                Thread.sleep(getPollSleepTime());
                queueCheckResult = checkBuildQueue(queueLocation, jobName);
                logger.debug("Queue Result ({})", queueCheckResult);
            } catch (JenkinsClientException ex) {
                logger.debug("Error Checking the build queue ({}) - {}", queueLocation, ex.getMessage());
                System.out.println(
                        String.format("Error Checking the build queue (%s) - %s", queueLocation, ex.getMessage()));
            } catch (InterruptedException ex) {
                //java.util.logging.Logger.getLogger(JenkinsClient.class.getName()).log(Level.SEVERE, null, ex);
            }
            if (queueCheckResult != null && queueCheckResult.hasBuildNumber()) {
                break;
            }

            pollCount++;
        }

        return queueCheckResult;
    }

    private BuildInfo checkBuildQueue(String queueUrl, String jobName) throws JenkinsClientException {
        BuildInfo result = null;
        String getResult = processGet(queueUrl, "api/json?tree=url,why,blocked,executable[number,url]");

        if (!StringUtils.isEmpty(getResult)) {
            try {
                JSONParser parser = new JSONParser();
                Object parsedObject = parser.parse(getResult);
                JSONObject executable = (JSONObject) ((JSONObject) parsedObject).get("executable");

                result = new BuildInfo();
                result.setName(jobName);
                result.setQueueUrl(queueUrl);
                result.setMessage((String) ((JSONObject) parsedObject).get("why"));

                if (executable != null) {
                    result.setBuildUrl((String) executable.get("url"));
                    result.setBuildNumber((Long) executable.get("number"));
                }

            } catch (Exception ex) {
                System.out.println("EX");
            }
        }

        return result;
    }

    /**
     * Execute a get request
     *
     * @param jenkinsUrl
     * @param getPath
     * @return Response body
     * @throws JenkinsClientException
     */
    public String processGet(String jenkinsUrl, String getPath) throws JenkinsClientException {
        String uri = createUrl(jenkinsUrl, getPath);

        logger.debug("Start executing Jenkins GET request to url=\"{}\"", uri);

        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet getRequest = new HttpGet(uri);

        if (getJenkinsUsername() != null && !StringUtils.isEmpty(getJenkinsUsername())) {
            UsernamePasswordCredentials creds = new UsernamePasswordCredentials(getJenkinsUsername(),
                    getJenkinsPassword());
            getRequest.addHeader(BasicScheme.authenticate(creds, "US-ASCII", false));
        }

        getRequest.addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
        getRequest.addHeader(HttpHeaders.ACCEPT, "application/json");
        String result = "";

        try {
            HttpResponse response = httpClient.execute(getRequest);
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                throw createHttpError(response);
            }

            BufferedReader br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
            StringBuilder sb = new StringBuilder(1024);
            String output;
            while ((output = br.readLine()) != null) {
                sb.append(output);
            }
            result = sb.toString();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            throw new JenkinsClientException("Server not available", e);
        } finally {
            httpClient.getConnectionManager().shutdown();
        }

        logger.debug("End executing Jenkins GET request to url=\"{}\" and receive this result={}", uri, result);

        return result;
    }

    /**
     * @param jenkinsUrl
     * @param path
     * @return
     */
    public String createUrl(String jenkinsUrl, String path) {
        String result;
        // URI uri;

        if (!jenkinsUrl.endsWith("/")) {
            jenkinsUrl += "/";
        }
        if (path.startsWith("/")) {
            path = path.substring(1);
        }

        try {
            //uri = new URI(jenkinsUrl + path);
            result = (jenkinsUrl + path).replace(" ", "%20");
        } catch (Exception e) {
            result = jenkinsUrl + path;
        }

        return result;
    }

    private JenkinsClientException createHttpError(HttpResponse response) {
        String message;
        try {
            StatusLine statusLine = response.getStatusLine();
            BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            String line;
            StringBuffer responsePayload = new StringBuffer();
            // Read response until the end
            while ((line = rd.readLine()) != null) {
                responsePayload.append(line);
            }

            message = String.format("request not successful: %d %s. Reason: %s", statusLine.getStatusCode(),
                    HttpStatus.getStatusText(statusLine.getStatusCode()), responsePayload);

            logger.info(message);

            if (new Integer(HttpStatus.SC_UNAUTHORIZED).equals(statusLine.getStatusCode())) {
                return new JenkinsClientException("Invalid credentials provided.");
            } else if (new Integer(HttpStatus.SC_NOT_FOUND).equals(statusLine.getStatusCode())) {
                return new JenkinsClientException("Jenkins: Request URL not found.");
            } else if (new Integer(HttpStatus.SC_BAD_REQUEST).equals(statusLine.getStatusCode())) {
                return new JenkinsClientException("Jenkins: Bad request. " + responsePayload);
            }
        } catch (IOException e) {
            return new JenkinsClientException("Jenkins: Can't read response");
        }

        return new JenkinsClientException(message);
    }

    static public void main(String[] args) throws JenkinsClientException {
        /*
         JenkinsClient jc = new JenkinsClient(null, "http://serenadeploy:9090/", "admin", "admin", null);
            
         System.out.println("Retrieving Jenkins Projects...");
         String projResponse = null;
         try {
        projResponse = jc.processGet(null, jc.getJenkinsUrl(), "rest/api/2/project");
         } catch (JiraClientException e) {
        System.out.print(e.toString());
         }
         System.out.println(projResponse);
            
         System.out.println("Retrieving Jenkins Issues for projects...");
           */

        JenkinsClient jc = new JenkinsClient("http://10.31.25.44:8080/jenkins/", "admin", "admin");
        //jc.processBuildPost("http://10.31.25.44:8080/jenkins/", "job/Build Job 3/build", "{\"parameter\": []}");
        System.out.println(jc.startBuild("Build Job 3", "{\"parameter\": []}"));

    }
}