Bug 460056 - Add rest API to access travis
diff --git a/org.eclipse.fx.travisci.client/.classpath b/org.eclipse.fx.travisci.client/.classpath
new file mode 100644
index 0000000..ace8266
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/.classpath
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.fx.travisci.client/.gitignore b/org.eclipse.fx.travisci.client/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/org.eclipse.fx.travisci.client/.project b/org.eclipse.fx.travisci.client/.project
new file mode 100644
index 0000000..f299442
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.fx.travisci.client</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/org.eclipse.fx.travisci.client/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.fx.travisci.client/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..714351a
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/org.eclipse.fx.travisci.client/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.fx.travisci.client/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/org.eclipse.fx.travisci.client/pom.xml b/org.eclipse.fx.travisci.client/pom.xml
new file mode 100644
index 0000000..2afddb2
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/pom.xml
@@ -0,0 +1,37 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.eclipse.fx</groupId>
+	<artifactId>org.eclipse.fx.travisci.client</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpclient-osgi</artifactId>
+			<version>4.3.6</version>
+		</dependency>
+		<dependency>
+			<groupId>com.google.code.gson</groupId>
+			<artifactId>gson</artifactId>
+			<version>2.1</version>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.11</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>3.1</version>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+</project>
\ No newline at end of file
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/BuildsEndpoint.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/BuildsEndpoint.java
new file mode 100644
index 0000000..5f6b4e5
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/BuildsEndpoint.java
@@ -0,0 +1,53 @@
+package org.eclipse.fx.travisci.client;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+import org.eclipse.fx.travisci.client.entities.Build;
+
+public interface BuildsEndpoint extends Endpoint {
+	public static class BuildsQuery {
+		public final List<String> ids;
+		public final Long repositoryId;
+		public final String slug;
+		public final String number;
+		public final String afterNumber;
+//		eventType
+		
+		private BuildsQuery(List<String> ids, Long repositoryId, String slug, String number, String afterNumber) {
+			super();
+			this.ids = ids == null ? Collections.emptyList() : Collections.unmodifiableList(ids);
+			this.repositoryId = repositoryId;
+			this.slug = slug;
+			this.number = number;
+			this.afterNumber = afterNumber;
+		}
+		
+		public static BuildsQuery byId(String id) {
+			return byIds(Collections.singletonList(id));
+		}
+		
+		public static BuildsQuery byIds(List<String> ids) {
+			return new BuildsQuery(ids, null, null, null, null);
+		}
+		
+		public static BuildsQuery byRepositoryId(long repositoryId, String number, String afterNumber) {
+			return new BuildsQuery(null, repositoryId, null, number, afterNumber);
+		}
+		
+		public static BuildsQuery byRepositoryId(long repositoryId) {
+			return byRepositoryId(repositoryId, null, null);
+		}
+		
+		public static BuildsQuery bySlug(String slug) {
+			return new BuildsQuery(null, null, slug, null, null);
+		}
+	}
+	
+	public Stream<Build> getBuilds(BuildsQuery query);
+	public void getBuilds(BuildsQuery query, Consumer<Stream<Build>> successConsumer, Consumer<Throwable> errorConsumer);
+	public void cancel(long buildId);
+	public void restart(long buildId);
+}
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/Endpoint.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/Endpoint.java
new file mode 100644
index 0000000..f83134d
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/Endpoint.java
@@ -0,0 +1,5 @@
+package org.eclipse.fx.travisci.client;
+
+public interface Endpoint {
+
+}
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/TravisCIClient.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/TravisCIClient.java
new file mode 100644
index 0000000..8b02ce3
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/TravisCIClient.java
@@ -0,0 +1,5 @@
+package org.eclipse.fx.travisci.client;
+
+public interface TravisCIClient {
+	public <E extends Endpoint> E createEndpoint(Class<E> endpoint);
+}
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/TravisCIClientFactory.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/TravisCIClientFactory.java
new file mode 100644
index 0000000..a552e29
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/TravisCIClientFactory.java
@@ -0,0 +1,6 @@
+package org.eclipse.fx.travisci.client;
+
+public interface TravisCIClientFactory {
+	public TravisCIClient createClient();
+	public TravisCIClient createClient(String hosturi);
+}
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/entities/Build.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/entities/Build.java
new file mode 100644
index 0000000..907fb6e
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/entities/Build.java
@@ -0,0 +1,20 @@
+package org.eclipse.fx.travisci.client.entities;
+
+import java.util.List;
+
+
+public interface Build {
+	public String id();
+	public long repository_id();
+	public String commit_id();
+	public String number();
+	public boolean pull_request();
+	public String pull_request_title();
+	public String pull_request_number();
+	public Config config();
+	public String state();
+	public String started_at();
+	public String finished_at();
+	public int duration();
+	public List<Long> job_ids();
+}
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/entities/Commit.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/entities/Commit.java
new file mode 100644
index 0000000..2f34269
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/entities/Commit.java
@@ -0,0 +1,15 @@
+package org.eclipse.fx.travisci.client.entities;
+
+public interface Commit {
+	public long id();
+	public String sha();
+	public String branch();
+	public String message();
+	public String committed_at();
+	public String author_name();
+	public String author_email();
+	public String committer_name();
+	public String committer_email();
+	public String compare_url();
+	public String pull_request_number();
+}
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/entities/Config.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/entities/Config.java
new file mode 100644
index 0000000..f894292
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/entities/Config.java
@@ -0,0 +1,7 @@
+package org.eclipse.fx.travisci.client.entities;
+
+// "config":{"language":"java","jdk":["oraclejdk8"],".result":"configured","os":"linux"}
+public interface Config {
+	public String language();
+	
+}
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/BuildsEndpointImpl.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/BuildsEndpointImpl.java
new file mode 100644
index 0000000..52c0a48
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/BuildsEndpointImpl.java
@@ -0,0 +1,68 @@
+package org.eclipse.fx.travisci.client.impl;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+import org.eclipse.fx.travisci.client.BuildsEndpoint;
+import org.eclipse.fx.travisci.client.entities.Build;
+import org.eclipse.fx.travisci.client.impl.entities.BuildsResult;
+
+import com.google.gson.GsonBuilder;
+
+public class BuildsEndpointImpl implements BuildsEndpoint {
+	private final TravisCIClientImpl client;
+	
+	public BuildsEndpointImpl(TravisCIClientImpl client) {
+		this.client = client;
+	}
+	
+	public Stream<Build> getBuilds(BuildsQuery query) {
+		Map<String, Object> parameters = new HashMap<String, Object>();
+		if( query.afterNumber != null ) {
+			parameters.put("after_number", query.afterNumber);			
+		}
+		if( query.ids != null ) {
+			parameters.put("ids",query.ids);	
+		}
+		if( query.number != null ) {
+			parameters.put("number",query.number);	
+		}
+		if( query.repositoryId != null ) {
+			parameters.put("repository_id",query.repositoryId);	
+		}
+		if( query.slug != null ) {
+			parameters.put("slug",query.slug);	
+		}
+		String request = client.sendGetRequest("/builds", parameters);
+		GsonBuilder gson = new GsonBuilder().setPrettyPrinting();
+		BuildsResult result = gson.create().fromJson(request, BuildsResult.class);
+		return ((List<Build>)result.builds()).stream(); 
+	}
+
+	@Override
+	public void getBuilds(BuildsQuery query, Consumer<Stream<Build>> successConsumer, Consumer<Throwable> errorConsumer) {
+		CompletableFuture.supplyAsync(() -> getBuilds(query)).whenComplete((s,t) -> {
+			if( t != null ) {
+				errorConsumer.accept(t);
+			} else {
+				successConsumer.accept(s);
+			}
+		});
+	}
+	
+	@Override
+	public void cancel(long buildId) {
+		// TODO Auto-generated method stub
+		
+	}
+	
+	@Override
+	public void restart(long buildId) {
+		// TODO Auto-generated method stub
+		
+	}
+}
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/TravisCIClientImpl.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/TravisCIClientImpl.java
new file mode 100644
index 0000000..8e60761
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/TravisCIClientImpl.java
@@ -0,0 +1,112 @@
+package org.eclipse.fx.travisci.client.impl;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.http.StatusLine;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.eclipse.fx.travisci.client.BuildsEndpoint;
+import org.eclipse.fx.travisci.client.Endpoint;
+import org.eclipse.fx.travisci.client.TravisCIClient;
+
+public class TravisCIClientImpl implements TravisCIClient {
+	private final String hostUri;
+	private final String applicationName;
+
+	private CloseableHttpClient client;
+	
+	public TravisCIClientImpl(String applicationName, String hostUri) {
+		this.hostUri = hostUri;
+		this.applicationName = applicationName;
+	}
+
+	public <E extends Endpoint> E createEndpoint(Class<E> endpoint) {
+		if (endpoint == BuildsEndpoint.class) {
+			return (E) new BuildsEndpointImpl(this);
+		}
+		return null;
+	}
+	
+	private CloseableHttpClient getClient() {
+		if( client == null ) {
+			try {
+				SSLContext sslcontext = SSLContext.getInstance("TLS");
+				sslcontext.init(new KeyManager[0], new TrustManager[] { new NoOpTrustManager() }, new SecureRandom());
+				client = HttpClients.custom().setSslcontext(sslcontext).build();			
+			} catch (NoSuchAlgorithmException e) {
+				throw new IllegalStateException(e);
+			} catch (KeyManagementException e) {
+				throw new IllegalStateException(e);
+			}
+		}
+		return client;
+	}
+
+	public final String sendGetRequest(String servicePath, Map<String, Object> parameters) {
+		try {
+			URIBuilder builder = new URIBuilder().setScheme("https").setHost(hostUri).setPath(servicePath);
+			for (Entry<String, Object> p : parameters.entrySet()) {
+				if (p.getValue() instanceof Collection<?>) {
+					for (Object o : (Collection<?>) p.getValue()) {
+						builder.addParameter(p.getKey(), o.toString());
+					}
+				} else {
+					builder.addParameter(p.getKey(), p.getValue().toString());
+				}
+			}
+
+			URI uri = builder.build();
+			System.err.println(uri);
+			HttpGet request = new HttpGet(uri);
+			request.setHeader("User-Agent", applicationName);
+			request.setHeader("Accept", "application/vnd.travis-ci.2+json");
+			CloseableHttpResponse response = getClient().execute(request);
+			StatusLine statusLine = response.getStatusLine();
+			int rv = statusLine.getStatusCode();
+			if (rv >= 200 && rv < 300) {
+				return EntityUtils.toString(response.getEntity());
+			}
+			throw new IllegalStateException("Request failed with HTTP-Status '" + statusLine + "'");
+		} catch (URISyntaxException e) {
+			throw new IllegalStateException(e);
+		} catch (ClientProtocolException e) {
+			throw new IllegalStateException(e);
+		} catch (IOException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+	
+	private static class NoOpTrustManager implements X509TrustManager {
+
+        @Override
+        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/BuildImpl.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/BuildImpl.java
new file mode 100644
index 0000000..21d6ef3
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/BuildImpl.java
@@ -0,0 +1,87 @@
+package org.eclipse.fx.travisci.client.impl.entities;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.fx.travisci.client.entities.Build;
+import org.eclipse.fx.travisci.client.entities.Config;
+
+public class BuildImpl implements Build {
+	private String id;
+	private long repository_id;
+	private String commit_id;
+	private String number;
+	private boolean pull_request;
+	private String pull_request_title;
+	private String pull_request_number;
+	private ConfigImpl config;
+	private String state;
+	private String started_at;
+	private String finished_at;
+	private int duration;
+	private List<Long> job_ids = new ArrayList<Long>();
+	
+	@Override
+	public String id() {
+		return id;
+	}
+	@Override
+	public long repository_id() {
+		return repository_id;
+	}
+	@Override
+	public String commit_id() {
+		return commit_id;
+	}
+	@Override
+	public String number() {
+		return number;
+	}
+	@Override
+	public boolean pull_request() {
+		return pull_request;
+	}
+	@Override
+	public String pull_request_title() {
+		return pull_request_title;
+	}
+	@Override
+	public String pull_request_number() {
+		return pull_request_number;
+	}
+	@Override
+	public Config config() {
+		return config;
+	}
+	@Override
+	public String state() {
+		return state;
+	}
+	@Override
+	public String started_at() {
+		return started_at;
+	}
+	@Override
+	public String finished_at() {
+		return finished_at;
+	}
+	@Override
+	public int duration() {
+		return duration;
+	}
+	@Override
+	public List<Long> job_ids() {
+		return job_ids;
+	}
+	
+	@Override
+	public String toString() {
+		return "BuildImpl [id=" + id + ", repository_id=" + repository_id + ", commit_id=" + commit_id + ", number="
+				+ number + ", pull_request=" + pull_request + ", pull_request_title=" + pull_request_title
+				+ ", pull_request_number=" + pull_request_number + ", config=" + config + ", state=" + state
+				+ ", started_at=" + started_at + ", finished_at=" + finished_at + ", duration=" + duration
+				+ ", job_ids=" + job_ids + "]";
+	}
+	
+	
+}
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/BuildsResult.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/BuildsResult.java
new file mode 100644
index 0000000..c87d1d2
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/BuildsResult.java
@@ -0,0 +1,20 @@
+package org.eclipse.fx.travisci.client.impl.entities;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.fx.travisci.client.entities.Build;
+
+public class BuildsResult {
+	private List<BuildImpl> builds = new ArrayList<BuildImpl>();
+	
+	public List<? extends Build> builds() {
+		return builds;
+	}
+	
+	@Override
+	public String toString() {
+		return "BuildsResult [builds=" + builds + "]";
+	}
+	
+}
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/CommitImpl.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/CommitImpl.java
new file mode 100644
index 0000000..d0cfddf
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/CommitImpl.java
@@ -0,0 +1,70 @@
+package org.eclipse.fx.travisci.client.impl.entities;
+
+import org.eclipse.fx.travisci.client.entities.Commit;
+
+public class CommitImpl implements Commit {
+	private long id;
+	private String sha;
+	private String branch;
+	private String message;
+	private String committed_at;
+	private String author_name;
+	private String author_email;
+	private String committer_name;
+	private String committer_email;
+	private String compare_url;
+	private String pull_request_number;
+	
+	@Override
+	public long id() {
+		return id;
+	}
+	@Override
+	public String sha() {
+		return sha;
+	}
+	@Override
+	public String branch() {
+		return branch;
+	}
+	@Override
+	public String message() {
+		return message;
+	}
+	@Override
+	public String committed_at() {
+		return committed_at;
+	}
+	@Override
+	public String author_name() {
+		return author_name;
+	}
+	@Override
+	public String author_email() {
+		return author_email;
+	}
+	@Override
+	public String committer_name() {
+		return committer_name;
+	}
+	@Override
+	public String committer_email() {
+		return committer_email;
+	}
+	@Override
+	public String compare_url() {
+		return compare_url;
+	}
+	@Override
+	public String pull_request_number() {
+		return pull_request_number;
+	}
+	@Override
+	public String toString() {
+		return "CommitImpl [id=" + id + ", sha=" + sha + ", branch=" + branch + ", message=" + message
+				+ ", committed_at=" + committed_at + ", author_name=" + author_name + ", author_email=" + author_email
+				+ ", committer_name=" + committer_name + ", committer_email=" + committer_email + ", compare_url="
+				+ compare_url + ", pull_request_number=" + pull_request_number + "]";
+	}
+	
+}
diff --git a/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/ConfigImpl.java b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/ConfigImpl.java
new file mode 100644
index 0000000..cb557aa
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/main/java/org/eclipse/fx/travisci/client/impl/entities/ConfigImpl.java
@@ -0,0 +1,18 @@
+package org.eclipse.fx.travisci.client.impl.entities;
+
+import org.eclipse.fx.travisci.client.entities.Config;
+
+public class ConfigImpl implements Config {
+	private String language;
+
+	@Override
+	public String language() {
+		return language;
+	}
+
+	@Override
+	public String toString() {
+		return "ConfigImpl [language=" + language + "]";
+	}
+	
+}
diff --git a/org.eclipse.fx.travisci.client/src/test/java/org/eclipse/fx/travisci/client/BuildsEndpointTestCase.java b/org.eclipse.fx.travisci.client/src/test/java/org/eclipse/fx/travisci/client/BuildsEndpointTestCase.java
new file mode 100644
index 0000000..072f160
--- /dev/null
+++ b/org.eclipse.fx.travisci.client/src/test/java/org/eclipse/fx/travisci/client/BuildsEndpointTestCase.java
@@ -0,0 +1,46 @@
+package org.eclipse.fx.travisci.client;
+
+import java.util.concurrent.CountDownLatch;
+
+import org.eclipse.fx.travisci.client.BuildsEndpoint.BuildsQuery;
+import org.eclipse.fx.travisci.client.impl.TravisCIClientImpl;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class BuildsEndpointTestCase {
+	@Test
+	public void testCreateEndPoint() {
+		TravisCIClientImpl c = new TravisCIClientImpl("travis-java-client-test", "api.travis-ci.org");
+		Assert.assertNotNull(c.createEndpoint(BuildsEndpoint.class));
+	}
+	
+	
+	@Test
+	public void testGetBuilds() {
+		TravisCIClientImpl c = new TravisCIClientImpl("travis-java-client-test", "api.travis-ci.org");
+		BuildsEndpoint endpoint = c.createEndpoint(BuildsEndpoint.class);
+		Assert.assertTrue(endpoint.getBuilds(BuildsQuery.byRepositoryId(3938495)).count() > 0);
+		Assert.assertTrue(endpoint.getBuilds(BuildsQuery.bySlug("tomsontom/compensator-samples")).count() > 0);
+	}
+	
+	@Test
+	public void testGetBuildsAsync() {
+		TravisCIClientImpl c = new TravisCIClientImpl("travis-java-client-test", "api.travis-ci.org");
+		BuildsEndpoint endpoint = c.createEndpoint(BuildsEndpoint.class);
+		CountDownLatch l = new CountDownLatch(1);
+		endpoint.getBuilds(BuildsQuery.byRepositoryId(3938495), (s) -> {
+			Assert.assertTrue(s.count() > 0);
+			l.countDown();
+		}, (t) -> 
+		{
+			l.countDown();
+			Assert.fail(t.getMessage());
+		});
+		try {
+			l.await();
+		} catch (InterruptedException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+}