package uk.org.floop.jenkins_pmd import groovy.json.JsonSlurper import hudson.FilePath import org.apache.http.HttpHost import org.apache.http.HttpResponse import org.apache.http.client.fluent.Executor import org.apache.http.client.fluent.Request import org.apache.http.entity.ContentType import org.apache.http.util.EntityUtils class Drafter implements Serializable { private PMD pmd private URI apiBase private HttpHost host private String user, pass enum Include { ALL("all"), OWNED("owned"), CLAIMABLE("claimable") public final String value Include(String v) { this.value = v } } Drafter(PMD pmd, String user, String pass) { this.pmd = pmd this.apiBase = new URI(pmd.config.pmd_api) this.host = new HttpHost(apiBase.getHost(), apiBase.getPort(), apiBase.getScheme()) this.user = user this.pass = pass } private Executor getExec() { Executor.newInstance() .auth(this.host, this.user, this.pass) .authPreemptive(this.host) } def listDraftsets(Include include=Include.ALL) { def js = new JsonSlurper() String path = (include == Include.ALL) ? "/v1/draftsets" : "/v1/draftsets?include=" + include.value def response = js.parse( getExec().execute( Request.Get(apiBase.resolve(path)) .addHeader("Accept", "application/json") .userAgent(PMDConfig.UA) ).returnContent().asStream() ) response } private static String errorMsg(HttpResponse response) { EntityUtils.consume(response.getEntity()) "${response.getStatusLine()} : ${EntityUtils.toString(response.getEntity())}" } def createDraftset(String label) { String displayName = URLEncoder.encode(label, "UTF-8") String path = "/v1/draftsets?display-name=${displayName}" HttpResponse response = getExec().execute( Request.Post(apiBase.resolve(path)) .addHeader("Accept", "application/json") .userAgent(PMDConfig.UA) ).returnResponse() if (response.getStatusLine().statusCode == 200) { return new JsonSlurper().parse(EntityUtils.toByteArray(response.getEntity())) } else { throw new DrafterException("Problem creating draftset ${errorMsg(response)}") } } def deleteGraph(String draftsetId, String graph) { String encGraph = URLEncoder.encode(graph, "UTF-8") String path = "/v1/draftset/${draftsetId}/graph?graph=${encGraph}&silent=true" HttpResponse response = getExec().execute( Request.Delete(apiBase.resolve(path)) .addHeader("Accept", "application/json") .userAgent(PMDConfig.UA) ).returnResponse() if (response.getStatusLine().statusCode == 200) { return new JsonSlurper().parse(EntityUtils.toByteArray(response.getEntity())) } else { throw new DrafterException("Problem deleting graph ${errorMsg(response)}") } } def deleteDraftset(String draftsetId) { String path = "/v1/draftset/${draftsetId}" HttpResponse response = getExec().execute( Request.Delete(apiBase.resolve(path)) .addHeader("Accept", "application/json") .userAgent(PMDConfig.UA) ).returnResponse() if (response.getStatusLine().statusCode == 202) { def jobObj = new JsonSlurper().parse(EntityUtils.toByteArray(response.getEntity())) waitForJob(apiBase.resolve(jobObj['finished-job'] as String), jobObj['restart-id'] as String) } else { throw new DrafterException("Problem deleting draftset ${errorMsg(response)}") } } def waitForJob(URI finishedJob, String restartId) { Executor exec = getExec() while (true) { HttpResponse jobResponse = exec.execute( Request.Get(finishedJob) .setHeader("Accept", "application/json") .userAgent(PMDConfig.UA) ).returnResponse() int status = jobResponse.getStatusLine().statusCode def jobObj try { jobObj = new JsonSlurper().parse(EntityUtils.toByteArray(jobResponse.getEntity())) } catch(e) { throw new DrafterException("Failed waiting for job ${errorMsg(jobResponse)}.\n${e}") } if (status == 404) { if (jobObj['restart-id'] != restartId) { throw new DrafterException("Failed waiting for job to finish, no/different restart-id ${errorMsg(jobResponse)}") } else { sleep(10000) } } else if (status == 200) { if (jobObj['restart-id'] != restartId) { throw new DrafterException("Failed waiting for job to finish, restart-id is different.") } else if (jobObj['type'] != 'ok') { throw new DrafterException("Pipeline error in ${jobObj.details?.pipeline?.name}. ${jobObj.message}") } else { break } } else { throw new DrafterException("Unexpected response waiting for job to complete: ${errorMsg(jobResponse)}") } } } def addData(String draftId, String fileName, String mimeType, String encoding, String graph=null) { String path = "/v1/draftset/${draftId}/data" if (graph) { String encGraph = URLEncoder.encode(graph, "UTF-8") path = path + "?graph=${encGraph}" } HttpResponse response = getExec().execute( Request.Put(apiBase.resolve(path)) .addHeader("Accept", "application/json") .userAgent(PMDConfig.UA) .bodyStream(new FilePath(new File(fileName)).read(), ContentType.create(mimeType, encoding)) ).returnResponse() if (response.getStatusLine().statusCode == 202) { def jobObj = new JsonSlurper().parse(EntityUtils.toByteArray(response.getEntity())) waitForJob(apiBase.resolve(jobObj['finished-job'] as String), jobObj['restart-id'] as String) } else { throw new DrafterException("Problem adding data ${errorMsg(response)}") } } def findDraftset(String displayName) { def drafts = listDraftsets(Include.OWNED) def draftset = drafts.find { it['display-name'] == displayName } if (draftset) { draftset } else { throw new DrafterException("Can't find draftset with the display-name '${displayName}'") } } def publishDraftset(String id) { String path = "/v1/draftset/${id}/publish" Executor exec = getExec() HttpResponse response = exec.execute( Request.Post(apiBase.resolve(path)) .addHeader("Accept", "application/json") .userAgent(PMDConfig.UA) ).returnResponse() if (response.getStatusLine().statusCode == 202) { def jobObj = new JsonSlurper().parse(EntityUtils.toByteArray(response.getEntity())) waitForJob(apiBase.resolve(jobObj['finished-job'] as String), jobObj['restart-id'] as String) if (pmd.config.empty_cache) { exec.execute( Request.Put(pmd.config.empty_cache) .addHeader("Accept", "application/json") .userAgent(PMDConfig.UA)) } if (pmd.config.sync_search) { exec.execute( Request.Put(pmd.config.sync_search) .addHeader("Accept", "application/json") .userAgent(PMDConfig.UA)) } } else { throw new DrafterException("Problem publishing draftset ${errorMsg(response)}") } } } class DrafterException extends Throwable { String message DrafterException(String message) { this.message = message } }