package com.github.dockerjava.core;

import java.util.ServiceLoader;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.DockerCmdExecFactory;
import com.github.dockerjava.core.DockerClientConfig.DockerClientConfigBuilder;

public class DockerClientBuilder {
	
	private static ServiceLoader<DockerCmdExecFactory> serviceLoader = ServiceLoader.load(DockerCmdExecFactory.class);

	private DockerClientImpl dockerClient = null;

	private DockerClientBuilder(DockerClientImpl dockerClient) {
		this.dockerClient = dockerClient;
	}

	public static DockerClientBuilder getInstance() {
		return new DockerClientBuilder(withDefaultDockerCmdExecFactory(DockerClientImpl.getInstance()));
	}
	
	public static DockerClientBuilder getInstance(DockerClientConfigBuilder dockerClientConfigBuilder) {
		return getInstance(dockerClientConfigBuilder.build());
	}

	public static DockerClientBuilder getInstance(DockerClientConfig dockerClientConfig) {
		return new DockerClientBuilder(withDefaultDockerCmdExecFactory(DockerClientImpl
				.getInstance(dockerClientConfig)));
	}

	public static DockerClientBuilder getInstance(String serverUrl) {
		return new DockerClientBuilder(withDefaultDockerCmdExecFactory(DockerClientImpl
				.getInstance(serverUrl)));
	}

	private static DockerClientImpl withDefaultDockerCmdExecFactory(
			DockerClientImpl dockerClient) {
		
		DockerCmdExecFactory dockerCmdExecFactory = getDefaultDockerCmdExecFactory();
		
		return dockerClient
				.withDockerCmdExecFactory(dockerCmdExecFactory);
	}

	public static DockerCmdExecFactory getDefaultDockerCmdExecFactory() {
		if(!serviceLoader.iterator().hasNext()) {
			throw new RuntimeException("Fatal: Can't find any implementation of '" + DockerCmdExecFactory.class.getName() +  "' in the current classpath.");
		}
		
		return serviceLoader.iterator().next();
	}

	public DockerClientBuilder withDockerCmdExecFactory(
			DockerCmdExecFactory dockerCmdExecFactory) {
		dockerClient = dockerClient
				.withDockerCmdExecFactory(dockerCmdExecFactory);
		return this;
	}

	public DockerClient build() {
		return dockerClient;
	}
}

@@ -454,16 +454,75 @@
  = null;
+%0A%09private DockerCmdExecFactory dockerCmdExecFactory = null;
 %0A%0A%09priva
@@ -705,40 +705,8 @@
 der(
-withDefaultDockerCmdExecFactory(
 Dock
@@ -732,17 +732,16 @@
 tance())
-)
 ;%0A%09%7D%0A%09%0A%09
@@ -1027,40 +1027,8 @@
 der(
-withDefaultDockerCmdExecFactory(
 Dock
@@ -1077,17 +1077,16 @@
 Config))
-)
 ;%0A%09%7D%0A%0A%09p
@@ -1187,40 +1187,8 @@
 der(
-withDefaultDockerCmdExecFactory(
 Dock
@@ -1232,276 +1232,8 @@
 rl))
-);%0A%09%7D%0A%0A%09private static DockerClientImpl withDefaultDockerCmdExecFactory(%0A%09%09%09DockerClientImpl dockerClient) %7B%0A%09%09%0A%09%09DockerCmdExecFactory dockerCmdExecFactory = getDefaultDockerCmdExecFactory();%0A%09%09%0A%09%09return dockerClient%0A%09%09%09%09.withDockerCmdExecFactory(dockerCmdExecFactory)
 ;%0A%09%7D
@@ -1654,30 +1654,172 @@
 ry) %7B%0A%09%09
+this.
 dockerC
-lient =
+mdExecFactory = dockerCmdExecFactory;%0A%09%09return this;%0A%09%7D%0A%0A%09public DockerClient build() %7B%0A%09        if(dockerCmdExecFactory != null) %7B%0A%09           
  dockerC
@@ -1823,21 +1823,16 @@
 erClient
-%0A%09%09%09%09
 .withDoc
@@ -1877,56 +1877,140 @@
 );%0A%09
-%09return this;%0A%09%7D%0A%0A%09public DockerClient build() %7B
+        %7D%0A%09        else %7B%0A%09            dockerClient.withDockerCmdExecFactory(getDefaultDockerCmdExecFactory());%0A%09        %7D%0A%09        
 %0A%09%09r

Allow for custom implementations of DockerCmdExecFactory to be specified without attempting to load default