/*******************************************************************************
 * Copyright (c) 2014, 2016 Red Hat Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Red Hat - Initial Contribution
 *******************************************************************************/
package org.eclipse.linuxtools.internal.docker.core;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import java.nio.file.FileSystems;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.ws.rs.ProcessingException;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.equinox.security.storage.EncodingUtils;
import org.eclipse.equinox.security.storage.ISecurePreferences;
import org.eclipse.equinox.security.storage.SecurePreferencesFactory;
import org.eclipse.equinox.security.storage.StorageException;
import org.eclipse.linuxtools.docker.core.Activator;
import org.eclipse.linuxtools.docker.core.DockerConnectionManager;
import org.eclipse.linuxtools.docker.core.DockerContainerNotFoundException;
import org.eclipse.linuxtools.docker.core.DockerException;
import org.eclipse.linuxtools.docker.core.DockerOpenConnectionException;
import org.eclipse.linuxtools.docker.core.DockerPingConnectionException;
import org.eclipse.linuxtools.docker.core.EnumDockerConnectionState;
import org.eclipse.linuxtools.docker.core.EnumDockerLoggingStatus;
import org.eclipse.linuxtools.docker.core.IDockerConfParameter;
import org.eclipse.linuxtools.docker.core.IDockerConnection;
import org.eclipse.linuxtools.docker.core.IDockerConnection2;
import org.eclipse.linuxtools.docker.core.IDockerConnectionInfo;
import org.eclipse.linuxtools.docker.core.IDockerConnectionSettings;
import org.eclipse.linuxtools.docker.core.IDockerConnectionSettings.BindingType;
import org.eclipse.linuxtools.docker.core.IDockerContainer;
import org.eclipse.linuxtools.docker.core.IDockerContainerConfig;
import org.eclipse.linuxtools.docker.core.IDockerContainerExit;
import org.eclipse.linuxtools.docker.core.IDockerContainerInfo;
import org.eclipse.linuxtools.docker.core.IDockerContainerListener;
import org.eclipse.linuxtools.docker.core.IDockerHostConfig;
import org.eclipse.linuxtools.docker.core.IDockerImage;
import org.eclipse.linuxtools.docker.core.IDockerImageBuildOptions;
import org.eclipse.linuxtools.docker.core.IDockerImageHierarchyNode;
import org.eclipse.linuxtools.docker.core.IDockerImageInfo;
import org.eclipse.linuxtools.docker.core.IDockerImageListener;
import org.eclipse.linuxtools.docker.core.IDockerImageSearchResult;
import org.eclipse.linuxtools.docker.core.IDockerIpamConfig;
import org.eclipse.linuxtools.docker.core.IDockerNetwork;
import org.eclipse.linuxtools.docker.core.IDockerNetworkConfig;
import org.eclipse.linuxtools.docker.core.IDockerNetworkCreation;
import org.eclipse.linuxtools.docker.core.IDockerPortBinding;
import org.eclipse.linuxtools.docker.core.IDockerProgressHandler;
import org.eclipse.linuxtools.docker.core.IDockerVersion;
import org.eclipse.linuxtools.docker.core.ILogger;
import org.eclipse.linuxtools.docker.core.IRegistryAccount;
import org.eclipse.linuxtools.docker.core.Messages;
import org.eclipse.linuxtools.internal.docker.core.DockerImage.DockerImageQualifier;
import org.eclipse.osgi.util.NLS;
import org.eclipse.tm.terminal.view.core.TerminalServiceFactory;
import org.eclipse.tm.terminal.view.core.interfaces.ITerminalService;
import org.eclipse.tm.terminal.view.core.interfaces.constants.ITerminalsConnectorConstants;

import com.spotify.docker.client.ContainerNotFoundException;
import com.spotify.docker.client.DockerCertificateException;
import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.DockerClient.AttachParameter;
import com.spotify.docker.client.DockerClient.BuildParam;
import com.spotify.docker.client.DockerClient.ExecCreateParam;
import com.spotify.docker.client.DockerClient.LogsParam;
import com.spotify.docker.client.DockerTimeoutException;
import com.spotify.docker.client.LogStream;
import com.spotify.docker.client.messages.AuthConfig;
import com.spotify.docker.client.messages.Container;
import com.spotify.docker.client.messages.ContainerConfig;
import com.spotify.docker.client.messages.ContainerCreation;
import com.spotify.docker.client.messages.ContainerExit;
import com.spotify.docker.client.messages.ContainerInfo;
import com.spotify.docker.client.messages.HostConfig;
import com.spotify.docker.client.messages.HostConfig.LxcConfParameter;
import com.spotify.docker.client.messages.Image;
import com.spotify.docker.client.messages.ImageInfo;
import com.spotify.docker.client.messages.ImageSearchResult;
import com.spotify.docker.client.messages.Info;
import com.spotify.docker.client.messages.Ipam;
import com.spotify.docker.client.messages.Network;
import com.spotify.docker.client.messages.NetworkConfig;
import com.spotify.docker.client.messages.PortBinding;
import com.spotify.docker.client.messages.Version;

/**
 * A connection to a Docker daemon. The connection may rely on Unix Socket or TCP connection (using the REST API). 
 * All low-level communication is delegated to a wrapped {@link DockerClient}.
 * 
 *
 */
public class DockerConnection
		implements IDockerConnection, IDockerConnection2, Closeable {

	// Builder allowing different binding modes (unix socket vs TCP connection)
	public static class Builder {

		private String name;

		public Builder name(final String name) {
			this.name = name;
			return this;
		}

		/**
		 * Creates a new {@link DockerConnection} using a Unix socket.
		 * 
		 * @param unixSocketConnectionSettings
		 *            the connection settings.
		 * @return a new {@link DockerConnection}
		 */
		public DockerConnection unixSocketConnection(
				final UnixSocketConnectionSettings unixSocketConnectionSettings) {
			return new DockerConnection(name, unixSocketConnectionSettings,
					null, null);
		}

		/**
		 * Creates a {@link DockerConnection} using a TCP connection.
		 * 
		 * @param tcpConnectionSettings
		 *            the {@link TCPConnectionSettings}
		 * @return a new {@link DockerConnection}
		 */
		public DockerConnection tcpConnection(
				final TCPConnectionSettings tcpConnectionSettings) {
			return new DockerConnection(name,
					tcpConnectionSettings, null,
					null);
		}

	}

	private String name;
	private IDockerConnectionSettings connectionSettings;
	private IDockerConnectionInfo connectionInfo;
	private final String username;
	private final Object imageLock = new Object();
	private final Object containerLock = new Object();
	private final Object actionLock = new Object();
	private final Object clientLock = new Object();
	private DockerClientFactory dockerClientFactory = new DockerClientFactory();
	private DockerClient client;

	private Map<String, Job> actionJobs;

	private Map<String, LogThread> loggingThreads = new HashMap<>();

	// containers sorted by name
	private List<IDockerContainer> containers;
	// containers indexed by id
	private Map<String, IDockerContainer> containersById = new HashMap<>();
	// flag to indicate if the state of the connection to the Docker daemon
	private EnumDockerConnectionState state = EnumDockerConnectionState.UNKNOWN;
	private List<IDockerImage> images;
	private Boolean isLocalConnection;

	ListenerList<IDockerContainerListener> containerListeners;
	ListenerList<IDockerImageListener> imageListeners;

	/**
	 * Constructor for a Unix socket based connection
	 */
	private DockerConnection(final String name,
			final UnixSocketConnectionSettings connectionSettings,
			final String username, final String password) {
		this.name = name;
		this.connectionSettings = connectionSettings;
		this.username = username;
		storePassword(connectionSettings.getPath(), username, password);
	}

	/**
	 * Constructor for a TCP-based connection
	 */
	private DockerConnection(final String name,
			final TCPConnectionSettings connectionSettings,
			final String username,
			final String password) {
		this.name = name;
		this.connectionSettings = connectionSettings;
		this.username = username;
		storePassword(connectionSettings.getHost(), username, password);
		// Add the container refresh manager to watch the containers list
		DockerContainerRefreshManager dcrm = DockerContainerRefreshManager
				.getInstance();
		addContainerListener(dcrm);
	}

	private void storePassword(String uri, String username, String passwd) {
		ISecurePreferences root = SecurePreferencesFactory.getDefault();
		String key = DockerConnection.getPreferencesKey(uri, username);
		ISecurePreferences node = root.node(key);
		try {
			if (passwd != null && !passwd.equals("")) //$NON-NLS-1$
				node.put("password", passwd, true /* encrypt */); //$NON-NLS-1$
		} catch (StorageException e) {
			Activator.log(e);
		}
	}

	public static String getPreferencesKey(String uri, String username) {
		String key = "/org/eclipse/linuxtools/docker/core/"; //$NON-NLS-1$
		key += uri + "/" + username; //$NON-NLS-1$
		return EncodingUtils.encodeSlashes(key);
	}

	@Override
	public boolean isOpen() {
		return this.client != null
				&& this.state == EnumDockerConnectionState.ESTABLISHED;
	}

	@Override
	public void open(boolean registerContainerRefreshManager)
			throws DockerException {
		// synchronized block to avoid concurrent attempts to open a connection
		// to the same Docker daemon
		synchronized (this) {
			if (this.client == null) {
				try {
					setClient(dockerClientFactory
							.getClient(this.connectionSettings));
					if (registerContainerRefreshManager) {
						// Add the container refresh manager to watch the
						// containers
						// list
						DockerContainerRefreshManager dcrm = DockerContainerRefreshManager
								.getInstance();
						addContainerListener(dcrm);
					}
				} catch (DockerCertificateException e) {
					setState(EnumDockerConnectionState.CLOSED);
					throw new DockerOpenConnectionException(
							NLS
							.bind(Messages.Open_Connection_Failure, this.name,
									this.getUri()),
							e);
				}
			}
			// then try to ping the Docker daemon to verify the connection
			ping();
		}
	}

	public DockerClient getClient() {
		return client;
	}

	public void setClient(final DockerClient client) {
		this.client = client;
		try {
			this.connectionInfo = getInfo();
		} catch (Exception e) {
			// ignore for now as this seems to occur too often and we always
			// check the value of connectionInfo before using
		}
	}
	/**
	 * Change the default {@link DockerClientFactory}
	 * 
	 * @param dockerClientFactory
	 *            the new {@link DockerClientFactory} to use when opening a
	 *            connection.
	 */
	public void setDockerClientFactory(
			final DockerClientFactory dockerClientFactory) {
		this.dockerClientFactory = dockerClientFactory;
	}

	@Override
	public EnumDockerConnectionState getState() {
		return this.state;
	}

	public void setState(final EnumDockerConnectionState state) {
		this.state = state;
		switch (state) {
		case UNKNOWN:
		case CLOSED:
			this.images = Collections.emptyList();
			this.containers = Collections.emptyList();
			this.containersById = new HashMap<>();
			notifyContainerListeners(this.containers);
			notifyImageListeners(this.images);
			break;
		case ESTABLISHED:
			this.getContainers(true);
			this.getImages(true);
			notifyContainerListeners(this.containers);
			notifyImageListeners(this.images);
			break;
		}
	}

	@Override
	public void ping() throws DockerException {
		try {
			if (this.client != null) {
				this.client.ping();
			} else {
				throw new DockerPingConnectionException(NLS.bind(
						Messages.Docker_Daemon_Ping_Failure, this.getName()));
			}
			setState(EnumDockerConnectionState.ESTABLISHED);
		} catch (com.spotify.docker.client.DockerException
				| InterruptedException e) {
			setState(EnumDockerConnectionState.CLOSED);
			throw new DockerPingConnectionException(NLS.bind(
					Messages.Docker_Daemon_Ping_Failure, this.getName()), e);
		}
	}

	@Override
	public void close() {
		synchronized (clientLock) {
			if (this.client != null) {
				this.client.close();
				this.client = null;
			}
			setState(EnumDockerConnectionState.CLOSED);
		}
	}

	@Override
	public IDockerConnectionInfo getInfo() throws DockerException {
		if (this.client == null) {
			return null;
		}
		try {
			final Info info = this.client.info();
			final Version version = this.client.version();
			return new DockerConnectionInfo(info, version);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException | InterruptedException e) {
			throw new DockerException(Messages.Docker_General_Info_Failure, e);
		}
	}
	
	@Override
	public String getName() {
		return name;
	}

	@Override
	public boolean setName(final String name) {
		if (!this.name.equals(name)) {
			this.name = name;
			return true;
		}
		return false;
	}

	@Override
	public String getUri() {
		if (this.connectionSettings
				.getType() == BindingType.UNIX_SOCKET_CONNECTION) {
			return ((UnixSocketConnectionSettings) this.connectionSettings)
					.getPath();
		} else {
			return ((TCPConnectionSettings) this.connectionSettings).getHost();
		}
	}

	@Override
	public IDockerConnectionSettings getSettings() {
		return this.connectionSettings;
	}

	@Override
	public boolean setSettings(
			final IDockerConnectionSettings connectionSettings) {
		if (!this.connectionSettings.equals(connectionSettings)) {
			// make sure no other operation using the underneath client occurs
			// while switching the connection settings.
			synchronized (clientLock) {
				this.connectionSettings = connectionSettings;
				if (this.client != null) {
					this.client.close();
				}
				this.state = EnumDockerConnectionState.UNKNOWN;
				this.client = null;
				new Job(NLS.bind(Messages.Open_Connection, this.getUri())) {

					@Override
					protected IStatus run(IProgressMonitor monitor) {
						try {
							open(true);
							ping();
						} catch (DockerException e) {
							Activator.logErrorMessage(
									NLS.bind(
											Messages.Docker_Daemon_Ping_Failure,
											this.getName()),
									e);
							return Status.CANCEL_STATUS;
						}
						return Status.OK_STATUS;
					}
				};
			}
			// getContainers(true);
			// getImages(true);
			return true;
		}
		return false;
	}

	@Override
	public String getUsername() {
		return username;
	}

	@Override
	public IDockerVersion getVersion() throws DockerException {
		try {
			Version version = client.version();
			return new DockerVersion(this, version);
		} catch (com.spotify.docker.client.DockerException
				| InterruptedException e) {
			throw new DockerException(Messages.Docker_General_Info_Failure, e);
		}
	}

	@Override
	public void addContainerListener(IDockerContainerListener listener) {
		if (containerListeners == null)
			containerListeners = new ListenerList<>(ListenerList.IDENTITY);
		containerListeners.add(listener);
	}

	@Override
	public void removeContainerListener(IDockerContainerListener listener) {
		if (containerListeners != null) {
			containerListeners.remove(listener);
		}
	}

	/**
	 * Get a copy of the client to use in parallel threads for long-standing
	 * operations such as logging or waiting until finished. The user of the
	 * copy should close it when the operation is complete.
	 * 
	 * @return copy of client
	 * @throws DockerException
	 * @throws DockerCertificateException
	 * @see DockerConnection#open(boolean)
	 */
	private DockerClient getClientCopy() throws DockerException {
		try {
			return dockerClientFactory.getClient(this.connectionSettings);
		} catch (DockerCertificateException e) {
			throw new DockerException(NLS.bind(Messages.Open_Connection_Failure,
					this.name, this.getUri()));
		}
	}

	// TODO: we might need something more fine grained, to indicate which
	// container changed, was added or was removed, so we can refresh the UI
	// accordingly.
	public void notifyContainerListeners(List<IDockerContainer> list) {
		if (containerListeners != null) {
			for (IDockerContainerListener listener : containerListeners) {
				listener.listChanged(this, list);
			}
		}
	}

	/**
	 * @return an fixed-size list of all {@link IDockerContainerListener}
	 */
	// TODO: include in IDockerConnection API
	public List<IDockerContainerListener> getContainerListeners() {
		if (this.containerListeners == null) {
			return Collections.emptyList();
		}
		final IDockerContainerListener[] result = new IDockerContainerListener[this.containerListeners
				.size()];
		final Object[] listeners = containerListeners.getListeners();
		for (int i = 0; i < listeners.length; i++) {
			result[i] = (IDockerContainerListener) listeners[i];
		}
		return Arrays.asList(result);
	}

	public Job getActionJob(String id) {
		synchronized (actionLock) {
			Job j = null;
			if (actionJobs != null) {
				return actionJobs.get(id);
			}
			return j;
		}
	}

	public void registerActionJob(String id, Job j) {
		synchronized (actionLock) {
			if (actionJobs == null)
				actionJobs = new HashMap<>();
			actionJobs.put(id, j);
		}
	}

	public void removeActionJob(String id, Job j) {
		synchronized (actionLock) {
			if (actionJobs != null && actionJobs.get(id) == j)
				actionJobs.remove(id);
		}
	}

	@Override
	public List<IDockerContainer> getContainers() {
		return getContainers(false);
	}

	@Override
	public List<IDockerContainer> getContainers(final boolean force) {
		if (this.state == EnumDockerConnectionState.CLOSED) {
			return Collections.emptyList();
		} else if (this.state == EnumDockerConnectionState.UNKNOWN) {
			try {
				open(true);
				getContainers(force);
			} catch (DockerException e) {
				Activator.log(e);
			}

		} else if (!isContainersLoaded() || force) {
			try {
				return listContainers();
			} catch (DockerException e) {
				Activator.log(e);
			}
		}
		return this.containers;
	}

	@Override
	public boolean isContainersLoaded() {
		return this.containers != null;
	}

	/**
	 * Class to perform logging of a container run to a given output stream
	 * (usually a console stream).
	 *
	 */
	private class LogThread extends AbstractKillableThread implements ILogger {
		private String id;
		private DockerClient copyClient;
		private OutputStream outputStream;
		private boolean follow;

		public LogThread(String id, DockerClient copyClient, boolean follow) {
			this.id = id;
			this.copyClient = copyClient;
			this.follow = follow;
		}

		@Override
		public LogThread clone() {
			return new LogThread(id, copyClient, follow);
		}

		@Override
		public void setOutputStream(OutputStream stream) {
			outputStream = stream;
		}

		@Override
		public void execute() throws InterruptedException, IOException {
			LogStream stream = null;
			try {
				// Add timestamps to log based on user preference
				IEclipsePreferences preferences = InstanceScope.INSTANCE
						.getNode("org.eclipse.linuxtools.docker.ui"); //$NON-NLS-1$

				boolean timestamps = preferences.getBoolean(
						"logTimestamp", true); //$NON-NLS-1$


				if (timestamps)
					stream = copyClient.logs(id, LogsParam.follow(),
							LogsParam.stdout(), LogsParam.stderr(),
							LogsParam.timestamps());
				else
					stream = copyClient.logs(id, LogsParam.follow(),
							LogsParam.stdout(), LogsParam.stderr());

				// First time through, don't sleep before showing log data
				int delayTime = 100;

				do {
					Thread.sleep(delayTime);
					// Second time in loop and following, pause a second to
					// allow other threads to do meaningful work
					delayTime = 500;
					while (stream.hasNext()) {
						ByteBuffer b = stream.next().content();
						byte[] bytes = new byte[b.remaining()];
						b.get(bytes);
						if (outputStream != null)
							outputStream.write(bytes);
					}
				} while (follow && !stop);
				listContainers();
			} catch (com.spotify.docker.client.DockerRequestException e) {
				Activator.logErrorMessage(
						ProcessMessages.getString("Monitor_Logs_Exception"), e); //$NON-NLS-1$
				throw new InterruptedException();
			} catch (com.spotify.docker.client.DockerException | IOException e) {
				Activator.logErrorMessage(
						ProcessMessages.getString("Monitor_Logs_Exception"), e); //$NON-NLS-1$
				throw new InterruptedException();
			} catch (InterruptedException e) {
				kill = true;
				Thread.currentThread().interrupt();
			} catch (Exception e) {
				Activator.logErrorMessage(
						ProcessMessages.getString("Monitor_Logs_Exception"), e); //$NON-NLS-1$
			} finally {
				follow = false;
				copyClient.close(); // we are done with copyClient..dispose
				if (stream != null)
					stream.close();
				if (outputStream != null)
					outputStream.close();
			}
		}
	}

	private List<IDockerContainer> listContainers()
			throws DockerException {
		final Map<String, IDockerContainer> updatedContainersById = new HashMap<>();
		List<IDockerContainer> sortedContainers;
		synchronized (containerLock) {
			try {
				final List<Container> nativeContainers = new ArrayList<>();
				synchronized (clientLock) {
					// Check that client is not null as this connection may have
					// been closed but there is an async request to update the
					// containers list left in the queue
					if (client == null) {
						// in that case the list becomes empty, which is fine is
						// there's no client.
						return Collections.emptyList();
					}
					nativeContainers.addAll(client.listContainers(
							DockerClient.ListContainersParam.allContainers()));
				}
				// We have a list of containers. Now, we translate them to our
				// own
				// core format in case we decide to change the underlying engine
				// in the future.
				for (Container nativeContainer : nativeContainers) {
					// For containers that have exited, make sure we aren't
					// tracking
					// them with a logging thread.
					if (nativeContainer.status() != null && nativeContainer
							.status().startsWith(Messages.Exited_specifier)) {
						synchronized (loggingThreads) {
							if (loggingThreads
									.containsKey(nativeContainer.id())) {
								loggingThreads.get(nativeContainer.id())
										.requestStop();
								loggingThreads.remove(nativeContainer.id());
							}
						}
					}
					// skip containers that are being removed
					if (nativeContainer.status() != null
							&& nativeContainer.status().equals(
									Messages.Removal_In_Progress_specifier)) {
						continue;
					}
					// re-use info from existing container with same id
					if (this.containers != null && this.containersById
							.containsKey(nativeContainer.id())) {
						final IDockerContainer container = this.containersById
								.get(nativeContainer.id());
						updatedContainersById.put(nativeContainer.id(),
								new DockerContainer(this, nativeContainer,
										container.info()));
					} else {
						updatedContainersById.put(nativeContainer.id(),
								new DockerContainer(this, nativeContainer));
					}
				}
			} catch (DockerTimeoutException e) {
				if (isOpen()) {
					Activator.log(
							new Status(IStatus.WARNING, Activator.PLUGIN_ID,
									Messages.Docker_Connection_Timeout, e));
					close();
				}
			} catch (com.spotify.docker.client.DockerException
					| InterruptedException e) {
				if (isOpen() && e.getCause() != null
						&& e.getCause().getCause() != null && e.getCause()
								.getCause() instanceof ProcessingException) {
					close();
				} else {
					throw new DockerException(e.getMessage());
				}
			} finally {
				this.containersById = updatedContainersById;
				sortedContainers = sort(
						updatedContainersById.values(),
						(container, otherContainer) -> container.name()
								.compareTo(otherContainer.name()));
				this.containers = sortedContainers;
			}
		}
		// perform notification outside of containerLock so we don't have a View
		// causing a deadlock
		// TODO: we should probably notify the listeners only if the containers
		// list changed.
		notifyContainerListeners(sortedContainers);
		return sortedContainers;
	}

	public Set<String> getContainerIdsWithLabels(Map<String, String> labels)
			throws DockerException {
		Set<String> labelSet = new HashSet<>();
		try {
			final List<Container> nativeContainers = new ArrayList<>();
			synchronized (clientLock) {
				// Check that client is not null as this connection may have
				// been closed but there is an async request to filter the
				// containers list left in the queue
				if (client == null) {
					// in that case the list becomes empty, which is fine is
					// there's no client.
					return Collections.emptySet();
				}
				DockerClient clientCopy = getClientCopy();
				DockerClient.ListContainersParam[] parms = new DockerClient.ListContainersParam[2];
				parms[0] = DockerClient.ListContainersParam.allContainers();
				// DockerClient doesn't support multiple labels with its
				// ListContainersParam so we have
				// to do a kludge and put in control chars ourselves and pretend
				// we have a label with no value.
				String separator = ""; //$NON-NLS-1$
				StringBuffer labelString = new StringBuffer();
				for (Entry<String, String> entry : labels.entrySet()) {
					labelString.append(separator);
					if (entry.getValue() == null || "".equals(entry.getValue())) //$NON-NLS-1$
						labelString.append(entry.getKey());
					else {
						labelString.append(
								entry.getKey() + "=" + entry.getValue()); //$NON-NLS-1$
					}
					separator = "\",\""; //$NON-NLS-1$
				}
				parms[1] = DockerClient.ListContainersParam
						.withLabel(labelString.toString());
				nativeContainers.addAll(clientCopy.listContainers(parms));
			}
			// We have a list of containers with labels. Now, we create a Set of
			// ids which contain those labels to use in filtering a list of
			// Containers
			for (Container nativeContainer : nativeContainers) {
				labelSet.add(nativeContainer.id());
			}
		} catch (DockerTimeoutException e) {
			if (isOpen()) {
				Activator.log(new Status(IStatus.WARNING, Activator.PLUGIN_ID,
						Messages.Docker_Connection_Timeout, e));
				close();
			}
		} catch (com.spotify.docker.client.DockerException
				| InterruptedException e) {
			if (isOpen() && e.getCause() != null
					&& e.getCause().getCause() != null
					&& e.getCause().getCause() instanceof ProcessingException) {
				close();
			} else {
				throw new DockerException(e.getMessage());
			}
		}
		return labelSet;
	}

	/**
	 * Sorts the given values using the given comparator and returns the result
	 * in a {@link List}
	 * 
	 * @param values
	 *            the values to sort
	 * @param comparator
	 *            the comparator to use
	 * @return the list of sorted values
	 */
	private <T> List<T> sort(final Collection<T> values,
			final Comparator<T> comparator) {
		final List<T> result = new ArrayList<>(values);
		Collections.sort(result, comparator);
		return result;
	}

	@Override
	public IDockerContainer getContainer(String id) {
		List<IDockerContainer> containers = getContainers();
		for (IDockerContainer container : containers) {
			if (container.id().equals(id)) {
				return container;
			}
		}
		return null;
	}

	@Override
	public IDockerContainerInfo getContainerInfo(final String id) {
		try {
			final ContainerInfo info = client.inspectContainer(id);
			return new DockerContainerInfo(info);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			Activator.logErrorMessage(
					ProcessMessages.getString("Container_Info_Exception"), e); //$NON-NLS-1$
			return null;
		} catch (com.spotify.docker.client.DockerException
				| InterruptedException e) {
			Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
					ProcessMessages.getFormattedString(
							"Container_Inspect_Exception", id), //$NON-NLS-1$
					e));
			return null;
		}
	}

	@Override
	public IDockerImageInfo getImageInfo(String id) {
		if (this.client == null) {
			return null;
		}
		try {
			final ImageInfo info = this.client.inspectImage(id);
			return new DockerImageInfo(info);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			Activator.logErrorMessage(
					ProcessMessages.getString("Image_Info_Exception"), e); //$NON-NLS-1$
			return null;
		} catch (com.spotify.docker.client.DockerException
				| InterruptedException e) {
			Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
					ProcessMessages.getFormattedString(
							"Image_Inspect_Exception", id), //$NON-NLS-1$
					e));
			return null;
		}
	}

	@Override
	public void addImageListener(IDockerImageListener listener) {
		if (imageListeners == null)
			imageListeners = new ListenerList<>(ListenerList.IDENTITY);
		imageListeners.add(listener);
	}

	@Override
	public void removeImageListener(IDockerImageListener listener) {
		if (imageListeners != null) {
			imageListeners.remove(listener);
		}
	}

	public void notifyImageListeners(List<IDockerImage> list) {
		if (imageListeners != null) {
			for (IDockerImageListener listener : imageListeners) {
				listener.listChanged(this, list);
			}
		}
	}

	/**
	 * @return an fixed-size list of all {@link IDockerImageListener}
	 */
	// TODO: include in IDockerConnection API
	public List<IDockerImageListener> getImageListeners() {
		if (this.imageListeners == null) {
			return Collections.emptyList();
		}
		final IDockerImageListener[] result = new IDockerImageListener[this.imageListeners
				.size()];
		final Object[] listeners = imageListeners.getListeners();
		for (int i = 0; i < listeners.length; i++) {
			result[i] = (IDockerImageListener) listeners[i];
		}
		return Arrays.asList(result);
	}

	@Override
	public List<IDockerImage> getImages() {
		return getImages(false);
	}

	/**
	 * @return the {@link IDockerImage} identified by the given {@code id} or
	 *         <code>null</code> if none was found.
	 * @param id
	 *            the {@link IDockerImage} id
	 */
	// TODO: declare the method in the interface to make it part of the API.
	public IDockerImage getImage(String id) {
		List<IDockerImage> images = getImages();
		for (IDockerImage image : images) {
			if (image.id().equals(id)) {
				return image;
			}
		}
		return null;
	}

	@Override
	public List<IDockerImage> getImages(final boolean force) {
		List<IDockerImage> latestImages;
		synchronized (imageLock) {
			latestImages = this.images;
		}
		if (this.state == EnumDockerConnectionState.CLOSED) {
			return Collections.emptyList();
		} else if (this.state == EnumDockerConnectionState.UNKNOWN) {
			try {
				open(true);
				latestImages = getImages(force);
			} catch (DockerException e) {
				Activator.log(e);
			}
		} else if (!isImagesLoaded() || force) {
			try {
				latestImages = listImages();
			} catch (DockerException e) {
				synchronized (imageLock) {
					this.images = Collections.emptyList();
				}
				Activator.log(e);
			}
		}
		return latestImages;
	}

	@Override
	public boolean isImagesLoaded() {
		return this.images != null;
	}

	// TODO: remove this method from the API
	@Override
	public List<IDockerImage> listImages() throws DockerException {
		final List<IDockerImage> tempImages = new ArrayList<>();
		synchronized (imageLock) {
			try {
				final List<Image> nativeImages = new ArrayList<>();
				synchronized (clientLock) {
					// Check that client is not null as this connection may have
					// been closed but there is an async request to update the
					// containers list left in the queue
					if (client == null) {
						// in that case the list becomes empty, which is fine is
						// there's no client.
						return Collections.emptyList();
					}
					nativeImages.addAll(client.listImages(
							DockerClient.ListImagesParam.allImages()));
				}
				// We have a list of images. Now, we translate them to our own
				// core format in case we decide to change the underlying engine
				// in the future. We also look for intermediate and dangling
				// images.
				for (Image nativeImage : nativeImages) {
					final DockerImageQualifier imageQualifier = resolveQualifier(
							nativeImage, nativeImages);
					// return one IDockerImage per raw image
					final List<String> repoTags = (nativeImage
							.repoTags() != null)
									? new ArrayList<>(nativeImage.repoTags())
									: new ArrayList<>();
					Collections.sort(repoTags);
					if (repoTags.isEmpty()) {
						repoTags.add("<none>:<none>"); //$NON-NLS-1$
					}
					final String repo = DockerImage
							.extractRepo(repoTags.get(0));
					final List<String> tags = Arrays
							.asList(DockerImage.extractTag(repoTags.get(0)));
					tempImages.add(new DockerImage(this, repoTags, repo, tags,
							nativeImage.id(), nativeImage.parentId(),
							nativeImage.created(), nativeImage.size(),
							nativeImage.virtualSize(), imageQualifier));
				}
			} catch (com.spotify.docker.client.DockerTimeoutException e) {
				if (isOpen()) {
					Activator.log(
							new Status(IStatus.WARNING, Activator.PLUGIN_ID,
									Messages.Docker_Connection_Timeout, e));
					close();
				}
			} catch (com.spotify.docker.client.DockerRequestException e) {
				throw new DockerException(e.message());
			} catch (com.spotify.docker.client.DockerException
					| InterruptedException e) {
				if (isOpen() && e.getCause() != null
						&& e.getCause().getCause() != null && e.getCause()
								.getCause() instanceof ProcessingException) {
					close();
				} else {
					throw new DockerException(
							NLS.bind(Messages.List_Docker_Images_Failure,
									this.getName()),
							e);
				}
			} finally {
				this.images = tempImages;
			}
		}
		// Perform notification outside of lock so that listener doesn't cause a
		// deadlock to occur
		notifyImageListeners(tempImages);
		return tempImages;
	}

	/**
	 * Resolves the {@link DockerImageQualifier} for the given
	 * {@code nativeImage} in the context of all {@code nativeImages}
	 * 
	 * @param nativeImage
	 *            the image to analyze
	 * @param nativeImages
	 *            all known images
	 * @return the corresponding {@link DockerImageQualifier}
	 */
	private static DockerImageQualifier resolveQualifier(
			final Image nativeImage, final List<Image> nativeImages) {
		final boolean hasTag = !(nativeImage.repoTags() == null
				|| (nativeImage.repoTags().size() == 1
						&& nativeImage.repoTags().contains("<none>:<none>"))); //$NON-NLS-1$
		final boolean hasChildImage = nativeImages.stream()
				.anyMatch(i -> nativeImage.id().equals(i.parentId()));
		// imtermediate image
		if (!hasTag && hasChildImage) {
			return DockerImageQualifier.INTERMEDIATE;
		}
		// dangling image
		if (!hasTag && !hasChildImage) {
			return DockerImageQualifier.DANGLING;
		}
		return DockerImageQualifier.TOP_LEVEL;
	}

	@Override
	public boolean hasImage(final String repository, final String tag) {
		for (IDockerImage image : getImages()) {
			for (String repoTag : image.repoTags()) {
				String tagExpr = (tag != null && !tag.isEmpty()) ? ":" + tag //$NON-NLS-1$
						: ""; //$NON-NLS-1$
				if (repoTag.equals(repository + tagExpr)) {
					return true;
				}
			}
		}
		return false;
	}

	public IDockerImage getImageByTag(final String tag) {
		for (IDockerImage image : getImages()) {
			for (String repoTag : image.repoTags()) {
				if (repoTag.equals(tag)) {
					return image;
				}
			}
		}
		return null;
	}

	@Override
	public IDockerProgressHandler getDefaultBuildImageProgressHandler(
			String image, int lines) {
		return new DefaultImageBuildProgressHandler(this, image, lines);
	}

	@Override
	public IDockerProgressHandler getDefaultPullImageProgressHandler(
			String image) {
		return new DefaultImagePullProgressHandler(this, image);
	}

	@Override
	public IDockerProgressHandler getDefaultPushImageProgressHandler(
			String image) {
		return new DefaultImagePushProgressHandler(this, image);
	}

	@Override
	public void pullImage(final String id, final IDockerProgressHandler handler)
			throws DockerException, InterruptedException {
		try {
			DockerProgressHandler d = new DockerProgressHandler(handler);
			client.pull(id, d);
			listImages();
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			DockerException f = new DockerException(e);
			throw f;
		}
	}

	@Override
	public void pullImage(final String imageId, final IRegistryAccount info, final IDockerProgressHandler handler)
			throws DockerException, InterruptedException, DockerCertificateException {
		try {
			final DockerClient client = dockerClientFactory
					.getClient(this.connectionSettings, info);
			final DockerProgressHandler d = new DockerProgressHandler(handler);
			client.pull(imageId, d);
			listImages();
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			DockerException f = new DockerException(e);
			throw f;
		}
	}

	@Override
	public List<IDockerImageSearchResult> searchImages(final String term) throws DockerException {
		try {
			final List<ImageSearchResult> searchResults = client.searchImages(term);
			final List<IDockerImageSearchResult> results = new ArrayList<>();
			for(ImageSearchResult r : searchResults) {
				if (r.getName().contains(term)) {
					results.add(new DockerImageSearchResult(r.getDescription(),
							r.isOfficial(), r.isAutomated(), r.getName(),
							r.getStarCount()));
				}
			}
			return results;
		} catch (com.spotify.docker.client.DockerException | InterruptedException e) {
			throw new DockerException(e);
		}
	}

	@Override
	public void pushImage(final String name, final IDockerProgressHandler handler)
			throws DockerException, InterruptedException {
		try {
			DockerProgressHandler d = new DockerProgressHandler(handler);
			client.push(name, d);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			DockerException f = new DockerException(e);
			throw f;
		}
	}

	@Override
	public void pushImage(final String name, final IRegistryAccount info, final IDockerProgressHandler handler)
			throws DockerException, InterruptedException {
		try {
			final DockerClient client = dockerClientFactory
					.getClient(this.connectionSettings, info);
			final DockerProgressHandler d = new DockerProgressHandler(handler);
			client.push(name, d);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException
				| DockerCertificateException e) {
			DockerException f = new DockerException(e);
			throw f;
		}
	}

	@Override
	public void removeImage(final String name) throws DockerException,
			InterruptedException {
		try {
			client.removeImage(name, true, false);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			DockerException f = new DockerException(e);
			throw f;
		}
	}

	@Override
	public void removeTag(final String tag) throws DockerException,
			InterruptedException {
		try {
			client.removeImage(tag, false, false);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			DockerException f = new DockerException(e);
			throw f;
		}
	}

	@Override
	public void tagImage(final String name, final String newTag) throws DockerException,
			InterruptedException {
		tagImage(name, newTag, false);
	}

	/**
	 * Adds a tag to an existing image while specifying the <code>force</code>
	 * flag.
	 * 
	 * @param name
	 *            the image id
	 * @param newTag
	 *            the new tag to add to the given image
	 * @param force
	 *            the {@code force} flag to force the operation if
	 *            <code>true</code>.
	 * @throws DockerException
	 *             in case of underlying problem (server error)
	 * @throws InterruptedException
	 *             if the thread was interrupted
	 */
	// TODO: add to the API in version 3.0.0
	public void tagImage(final String name, final String newTag,
			final boolean force) throws DockerException, InterruptedException {
		try {
			client.tag(name, newTag, force);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			DockerException f = new DockerException(e);
			throw f;
		}
	}

	@Override
	public String buildImage(final IPath path,
			final IDockerProgressHandler handler)
					throws DockerException, InterruptedException {
		try {
			final DockerProgressHandler d = new DockerProgressHandler(handler);
			final java.nio.file.Path p = FileSystems.getDefault()
					.getPath(path.makeAbsolute().toOSString());
			String res = getClientCopy().build(p, d,
					BuildParam.create("forcerm", "true")); //$NON-NLS-1$ //$NON-NLS-2$
			return res;
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException | IOException e) {
			DockerException f = new DockerException(e);
			throw f;
		}
	}

	@Override
	public String buildImage(final IPath path, final String name,
			final IDockerProgressHandler handler)
					throws DockerException, InterruptedException {
		try {
			DockerProgressHandler d = new DockerProgressHandler(handler);
			java.nio.file.Path p = FileSystems.getDefault().getPath(
					path.makeAbsolute().toOSString());
			String res = getClientCopy().build(p, name, d,
					BuildParam.create("forcerm", "true")); //$NON-NLS-1$ $NON-NLS-2$
			return res;
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException | IOException e) {
			DockerException f = new DockerException(e);
			throw f;
		}
	}

	/**
	 * Builds an {@link IDockerImage}
	 * 
	 * @param path
	 *            path to the build context
	 * @param name
	 *            optional name and tag of the image to build
	 * @param handler
	 *            progress handler
	 * @param buildOptions
	 *            build options
	 * @return the id of the {@link IDockerImage} that was build
	 * @throws DockerException
	 *             if building image failed
	 * @throws InterruptedException
	 *             if the thread was interrupted
	 */
	// TODO: add this method in the public interface
	public String buildImage(final IPath path, final String name,
			final IDockerProgressHandler handler,
			final Map<String, Object> buildOptions)
					throws DockerException, InterruptedException {
		try {
			final DockerProgressHandler d = new DockerProgressHandler(handler);
			final java.nio.file.Path p = FileSystems.getDefault()
					.getPath(path.makeAbsolute().toOSString());
			String res = getClientCopy().build(p, name, d,
					getBuildParameters(buildOptions));
			return res;
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException | IOException e) {
			DockerException f = new DockerException(e);
			throw f;
		}
	}

	/**
	 * Converts the given {@link Map} of build options into an array of
	 * {@link BuildParameter} when the build options are set a value different
	 * from the default value.
	 * 
	 * @param buildOptions
	 *            the build options
	 * @return an array of relevant {@link BuildParameter}, an empty array if
	 *         the given {@code buildOptions} is empty or <code>null</code>.
	 */
	private BuildParam[] getBuildParameters(
			final Map<String, Object> buildOptions) {
		if (buildOptions == null) {
			return new BuildParam[0];
		}
		final List<BuildParam> buildParameters = new ArrayList<>();
		for (Entry<String, Object> entry : buildOptions.entrySet()) {
			final Object optionName = entry.getKey();
			final Object optionValue = entry.getValue();

			if (optionName.equals(IDockerImageBuildOptions.QUIET_BUILD)
					&& optionValue.equals(true)) {
				buildParameters.add(BuildParam.create("q", "true")); //$NON-NLS-1$ $NON-NLS-2$
			} else if (optionName.equals(IDockerImageBuildOptions.NO_CACHE)
					&& optionValue.equals(true)) {
				buildParameters.add(BuildParam.create("nocache", "true")); //$NON-NLS-1$ $NON-NLS-2$
			} else if (optionName
					.equals(IDockerImageBuildOptions.RM_INTERMEDIATE_CONTAINERS)
					&& optionValue.equals(false)) {
				buildParameters.add(BuildParam.create("rm", "false")); //$NON-NLS-1$ $NON-NLS-2$
			} else if (optionName
					.equals(IDockerImageBuildOptions.FORCE_RM_INTERMEDIATE_CONTAINERS)
					&& optionValue.equals(true)) {
				buildParameters.add(BuildParam.create("forcerm", "true")); //$NON-NLS-1$ $NON-NLS-2$
			}
		}
		return buildParameters.toArray(new BuildParam[0]);
	}

	public void save() {
		// Currently we have to save all clouds instead of just this one
		DockerConnectionManager.getInstance().saveConnections();
	}
	
	@Override
	@Deprecated
	public String createContainer(IDockerContainerConfig c)
			throws DockerException, InterruptedException {
		IDockerHostConfig hc = new DockerHostConfig(HostConfig.builder()
				.build());
		return createContainer(c, hc);
	}

	@Override
	@Deprecated
	public String createContainer(final IDockerContainerConfig c,
			final String containerName)
			throws DockerException, InterruptedException {
		IDockerHostConfig hc = new DockerHostConfig(HostConfig.builder()
				.build());
		return createContainer(c, hc, containerName);
	}

	@Override
	public String createContainer(final IDockerContainerConfig c,
			final IDockerHostConfig hc) throws DockerException,
			InterruptedException {
		return createContainer(c, hc, null);
	}

	@Override
	public String createContainer(final IDockerContainerConfig c,
			IDockerHostConfig hc,
			final String containerName)
			throws DockerException, InterruptedException {

		try {
			HostConfig.Builder hbuilder = HostConfig.builder()
					.containerIDFile(hc.containerIDFile())
					.publishAllPorts(hc.publishAllPorts())
					.privileged(hc.privileged()).networkMode(hc.networkMode());
			if (hc.binds() != null)
				hbuilder.binds(hc.binds());
			if (hc.dns() != null)
				hbuilder.dns(hc.dns());
			if (hc.dnsSearch() != null)
				hbuilder.dnsSearch(hc.dnsSearch());
			if (hc.links() != null)
				hbuilder.links(hc.links());
			if (hc.lxcConf() != null) {
				List<IDockerConfParameter> lxcconf = hc.lxcConf();
				ArrayList<LxcConfParameter> lxcreal = new ArrayList<>();
				for (IDockerConfParameter param : lxcconf) {
					lxcreal.add(new LxcConfParameter(param.key(), param.value()));
				}
				hbuilder.lxcConf(lxcreal);
			}
			if (hc.portBindings() != null) {
				Map<String, List<IDockerPortBinding>> bindings = hc
						.portBindings();
				HashMap<String, List<PortBinding>> realBindings = new HashMap<>();

				for (Entry<String, List<IDockerPortBinding>> entry : bindings
						.entrySet()) {
					String key = entry.getKey();
					List<IDockerPortBinding> bindingList = entry.getValue();
					ArrayList<PortBinding> newList = new ArrayList<>();
					for (IDockerPortBinding binding : bindingList) {
						newList.add(PortBinding.of(binding.hostIp(),
								binding.hostPort()));
					}
					realBindings.put(key, newList);
				}
				hbuilder.portBindings(realBindings);
			}
			if (hc.volumesFrom() != null) {
				hbuilder.volumesFrom(hc.volumesFrom());
			}
			if (hc.securityOpt() != null) {
				hbuilder.securityOpt(hc.securityOpt());
			}
			// FIXME: add the 'memory()' method in the IDockerHostConfig
			// interface
			if (((DockerHostConfig) hc).memory() != null) {
				hbuilder.memory(((DockerHostConfig) hc).memory());
			}
			// FIXME: add the 'cpuShares()' method in the IDockerHostConfig
			// interface
			if (((DockerHostConfig) hc).cpuShares() != null
					&& ((DockerHostConfig) hc).cpuShares().longValue() > 0) {
				hbuilder.cpuShares(((DockerHostConfig) hc).cpuShares());
			}

			ContainerConfig.Builder builder = ContainerConfig.builder()
					.hostname(c.hostname()).domainname(c.domainname())
					.user(c.user()).attachStdin(c.attachStdin())
					.attachStdout(c.attachStdout())
					.attachStderr(c.attachStderr()).tty(c.tty())
					.openStdin(c.openStdin()).stdinOnce(c.stdinOnce())
					.cmd(c.cmd()).image(c.image())
					.hostConfig(hbuilder.build())
					.workingDir(c.workingDir())
					.labels(c.labels())
					.networkDisabled(c.networkDisabled());
			// For those fields that are Collections and not set, they will be null.
			// We can't use their values to set the builder's fields as they are
			// expecting non-null Collections to copy over. In those cases, we just
			// don't set those fields in the builder.
			if (c.portSpecs() != null) {
				builder = builder.portSpecs(c.portSpecs());
			}
			if (c.exposedPorts() != null) {
				builder = builder.exposedPorts(c.exposedPorts());
			}
			if (c.env() != null) {
				builder = builder.env(c.env());
			}
			if (c.volumes() != null) {
				builder = builder.volumes(c.volumes());
			}
			if (c.entrypoint() != null) {
				builder = builder.entrypoint(c.entrypoint());
			}
			if (c.onBuild() != null) {
				builder = builder.onBuild(c.onBuild());
			}

			// create container with default random name if an empty/null
			// containerName argument was passed
			final ContainerCreation creation = client
					.createContainer(builder.build(),
					(containerName != null && !containerName.isEmpty())
							? containerName : null);
			final String id = creation.id();
			// force a refresh of the current containers to include the new one
			listContainers();
			return id;
		} catch (ContainerNotFoundException e) {
			throw new DockerContainerNotFoundException(e);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e);
		}
	}

	@Override
	public void stopContainer(final String id) throws DockerException,
			InterruptedException {
		try {
			// stop container or kill after 10 seconds
			client.stopContainer(id, 10); // allow up to 10 seconds to stop
			synchronized (loggingThreads) {
				if (loggingThreads.containsKey(id)) {
					loggingThreads.get(id).kill();
					loggingThreads.remove(id);
				}
			}
			// list of containers needs to be updated once the given container is stopped, to reflect it new state.
			listContainers();
		} catch (ContainerNotFoundException e) {
			throw new DockerContainerNotFoundException(e);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public void killContainer(final String id) throws DockerException,
			InterruptedException {
		try {
			// kill container
			client.killContainer(id);
			synchronized (loggingThreads) {
				if (loggingThreads.containsKey(id)) {
					loggingThreads.get(id).kill();
					loggingThreads.remove(id);
				}
			}
			listContainers(); // update container list
		} catch (ContainerNotFoundException e) {
			throw new DockerContainerNotFoundException(e);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			// Permit kill to fail silently even on non-running containers
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public void pauseContainer(final String id) throws DockerException,
			InterruptedException {
		try {
			// pause container
			client.pauseContainer(id);
			listContainers(); // update container list
		} catch (ContainerNotFoundException e) {
			throw new DockerContainerNotFoundException(e);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public void unpauseContainer(final String id, final OutputStream stream)
			throws DockerException, InterruptedException {
		try {
			// unpause container
			client.unpauseContainer(id);
			if (stream != null) {
				synchronized (loggingThreads) {
					LogThread t = loggingThreads.get(id);
					if (t == null || !t.isAlive()) {
						t = new LogThread(id, getClientCopy(), true);
						loggingThreads.put(id, t);
						t.setOutputStream(stream);
						t.start();
					} else {
						// we aren't going to use the stream given...close it
						try {
							stream.close();
						} catch (IOException e) {
							// do nothing...we tried to close the stream
						}
					}
				}
			}
			listContainers(); // update container list
		} catch (ContainerNotFoundException e) {
			throw new DockerContainerNotFoundException(e);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public void removeContainer(final String id) throws DockerException,
			InterruptedException {
		try {
			// kill container
			client.removeContainer(id);
			listContainers(); // update container list
		} catch (ContainerNotFoundException e) {
			throw new DockerContainerNotFoundException(e);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	@Deprecated
	public void startContainer(String id, IDockerHostConfig config,
			OutputStream stream)
			throws DockerException, InterruptedException {
		startContainer(id, stream);
	}

	@Override
	@Deprecated
	public void startContainer(String id, String loggingId,
			IDockerHostConfig config, OutputStream stream)
			throws DockerException, InterruptedException {
		startContainer(id, loggingId, stream);
	}

	@Override
	public void startContainer(final String id, final OutputStream stream)
			throws DockerException, InterruptedException {
		try {
			// start container
			client.startContainer(id);
			// Log the started container if a stream is provided
			final IDockerContainerInfo containerInfo = getContainerInfo(id);
			if (stream != null && containerInfo != null
					&& containerInfo.config() != null
					&& !containerInfo.config().tty()) {
				// display logs for container
				synchronized (loggingThreads) {
					LogThread t = loggingThreads.get(id);
					if (t == null || !t.isAlive()) {
						t = new LogThread(id, getClientCopy(), true);
						loggingThreads.put(id, t);
						t.setOutputStream(stream);
						t.start();
					}
				}
			}
			// list of containers needs to be refreshed once the container started, to reflect it new state.
			listContainers(); 
		} catch (ContainerNotFoundException e) {
			throw new DockerContainerNotFoundException(e);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public void startContainer(String id, String loggingId, OutputStream stream)
			throws DockerException, InterruptedException {
		try {
			// start container with host config
			client.startContainer(id);
			// Log the started container based on user preference
			// Log the started container based on user preference
			// Log the started container based on user preference
			IEclipsePreferences preferences = InstanceScope.INSTANCE
					.getNode("org.eclipse.linuxtools.docker.ui"); //$NON-NLS-1$

			boolean autoLog = preferences.getBoolean("autoLogOnStart", true); //$NON-NLS-1$

			if (autoLog && !getContainerInfo(id).config().tty()) {
				synchronized (loggingThreads) {
					LogThread t = loggingThreads.get(loggingId);
					if (t == null || !t.isAlive()) {
						t = new LogThread(id, getClientCopy(), true);
						loggingThreads.put(loggingId, t);
						t.setOutputStream(stream);
						t.start();
					}
				}
			}
			// update container list
			listContainers();
		} catch (ContainerNotFoundException e) {
			throw new DockerContainerNotFoundException(e);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e);
		}
	}

	@Override
	public void restartContainer(String id, int secondsToWait)
			throws DockerException, InterruptedException {
		restartContainer(id, secondsToWait, null);
	}

	public void restartContainer(final String id, int secondsToWait,
			final OutputStream stream)
			throws DockerException, InterruptedException {
		try {
			// restart container
			client.restartContainer(id, secondsToWait);
			// Log the started container if a stream is provided
			final IDockerContainerInfo containerInfo = getContainerInfo(id);
			if (stream != null && containerInfo != null
					&& containerInfo.config() != null
					&& !containerInfo.config().tty()) {
				// display logs for container
				synchronized (loggingThreads) {
					LogThread t = loggingThreads.get(id);
					if (t == null || !t.isAlive()) {
						t = new LogThread(id, getClientCopy(), true);
						loggingThreads.put(id, t);
						t.setOutputStream(stream);
						t.start();
					}
				}
			}
			// list of containers needs to be refreshed once the container
			// started, to reflect it new state.
			listContainers();
		} catch (ContainerNotFoundException e) {
			throw new DockerContainerNotFoundException(e);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}


	@Override
	public void commitContainer(final String id, final String repo, final String tag,
			final String comment, final String author) throws DockerException {
		ContainerInfo info;
		try {
			info = client.inspectContainer(id);
			client.commitContainer(id, repo, tag, info.config(), comment,
					author);
			// update images list
			// FIXME: are we refreshing the list of images twice ?
			listImages();
			getImages(true);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException
				| InterruptedException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public InputStream copyContainer(final String id, final String path)
			throws DockerException, InterruptedException {
		InputStream stream;
		try {
			if (this.connectionInfo != null) {
				String apiversion = connectionInfo.getApiVersion();
				if (apiversion != null) {
					String[] tokens = apiversion.split("\\."); //$NON-NLS-1$
					if (tokens.length > 1) {
						try {
							int major = Integer.valueOf(tokens[0]);
							int minor = Integer.valueOf(tokens[1]);
							if (major > 1 || minor >= 24) {
								throw new DockerException(
										DockerMessages.getFormattedString(
												"DockerClientVersionTooLow.error", //$NON-NLS-1$
												"copyContainer", "1.24")); //$NON-NLS-1$ //$NON-NLS-2$
							}
						} catch (NumberFormatException e) {
							// ignore for now and let things occur
						}
					}
				}
			}
			DockerClient copy = getClientCopy();
			stream = copy.copyContainer(id, path);
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
		return stream;
	}

	public boolean isLocal() {
		if (isLocalConnection != null)
			return isLocalConnection.booleanValue();
		isLocalConnection = new Boolean(false);
		if (connectionSettings
				.getType() == BindingType.UNIX_SOCKET_CONNECTION) {
			isLocalConnection = new Boolean(true);
		} else if (connectionSettings.getType() == BindingType.TCP_CONNECTION) {
			TCPConnectionSettings settings = (TCPConnectionSettings) connectionSettings;
			try {
				InetAddress addr = InetAddress.getByName(settings.getAddr());
				if (addr.isAnyLocalAddress() || addr.isLoopbackAddress()) {
					isLocalConnection = new Boolean(true);
				} else {
					// Check if the address is defined on any interface
					try {
						isLocalConnection = new Boolean(NetworkInterface
								.getByInetAddress(addr) != null);
					} catch (SocketException e) {
						isLocalConnection = new Boolean(false);
					}
				}
			} catch (UnknownHostException e) {
				// should not happen
				Activator.log(e);
			}
		}
		return isLocalConnection.booleanValue();
	}

	@Override
	public void copyToContainer(final String directory, final String id,
			final String path)
			throws DockerException, InterruptedException, IOException {
		try {
			DockerClient copy = getClientCopy();
			java.nio.file.Path dirPath = FileSystems.getDefault()
					.getPath(directory);
			copy.copyToContainer(dirPath, id, path);
			copy.close(); /* dispose of client copy now that we are done */
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public int auth(IRegistryAccount cfg)
			throws DockerException, InterruptedException {
		try {
			AuthConfig authConfig = AuthConfig.builder()
					.username(new String(cfg.getUsername()))
					.password(cfg.getPassword() != null
							? new String(cfg.getPassword()) : null)
					.email(new String(cfg.getEmail()))
					.serverAddress(new String(cfg.getServerAddress())).build();
			return client.auth(authConfig);
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	public EnumDockerLoggingStatus loggingStatus(final String id) {
		synchronized (loggingThreads) {
			LogThread t = loggingThreads.get(id);
			if (t == null)
				return EnumDockerLoggingStatus.LOGGING_NONE;
			if (t.isAlive())
				return EnumDockerLoggingStatus.LOGGING_ACTIVE;
			return EnumDockerLoggingStatus.LOGGING_COMPLETE;
		}
	}

	@Override
	public void stopLoggingThread(final String id) {
		synchronized (loggingThreads) {
			LogThread t = loggingThreads.get(id);
			if (t != null)
				t.requestStop();
		}
		while (loggingStatus(id) == EnumDockerLoggingStatus.LOGGING_ACTIVE) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				Activator.log(e);
			}
		}

	}

	@Override
	public void logContainer(final String id, final OutputStream stream)
			throws DockerException, InterruptedException {
		try {
			// Figure out if we are logging a running container or not
			// Pass that info to see whether the LogThread should just terminate
			// or keep running
			synchronized (loggingThreads) {
				ContainerInfo info = client.inspectContainer(id);
				LogThread t = loggingThreads.get(id);
				if (t == null || !t.isAlive()) {
					t = new LogThread(id, getClientCopy(), info.state()
							.running());
					loggingThreads.put(id, t);
					t.setOutputStream(stream);
					t.start();
				} else {
					// we aren't going to use the stream given...close it
					try {
						stream.close();
					} catch (IOException e) {
						// do nothing...we tried to close the stream
					}
				}
			}
		} catch (ContainerNotFoundException e) {
			throw new DockerContainerNotFoundException(e);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public void attachLog(final String id, final OutputStream out,
			final OutputStream err)
			throws DockerException, InterruptedException, IOException {
		DockerClient copyClient;
		try {
			copyClient = getClientCopy();
			LogStream stream = copyClient.logs(id, LogsParam.follow(),
					LogsParam.stdout(), LogsParam.stderr());
			stream.attach(out, err);
			stream.close();
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public IDockerContainerExit waitForContainer(final String id)
			throws DockerException, InterruptedException {
		try {
			// wait for container to exit
			DockerClient copy = getClientCopy();
			ContainerExit x = copy.waitContainer(id);
			DockerContainerExit exit = new DockerContainerExit(x.statusCode());
			listContainers(); // update container list
			copy.close(); // dispose of copy now we are finished
			return exit;
		} catch (ContainerNotFoundException e) {
			throw new DockerContainerNotFoundException(e);
		} catch (com.spotify.docker.client.DockerRequestException e) {
			throw new DockerException(e.message());
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	public void attachCommand(final String id, final InputStream in,
			@SuppressWarnings("unused") final OutputStream out)
					throws DockerException {

		final byte[] prevCmd = new byte[1024];
		try {
			final LogStream pty_stream = client.attachContainer(id,
					AttachParameter.STDIN, AttachParameter.STDOUT,
					AttachParameter.STDERR, AttachParameter.STREAM,
					AttachParameter.LOGS);
			final IDockerContainerInfo info = getContainerInfo(id);
			final boolean isTtyEnabled = info.config().tty();
			final boolean isOpenStdin = info.config().openStdin();

			if (isTtyEnabled) {
				openTerminal(pty_stream, info.name());
			}

			// Data from the given input stream
			// Written to container's STDIN
			Thread t_in = new Thread(() -> {
				byte[] buff = new byte[1024];
				int n;
				try {
					WritableByteChannel pty_out = HttpHijackWorkaround
							.getOutputStream(pty_stream, getUri());
					while ((n = in.read(buff)) != -1
							&& getContainerInfo(id).state().running()) {
						synchronized (prevCmd) {
							pty_out.write(ByteBuffer.wrap(buff, 0, n));
							for (int i = 0; i < prevCmd.length; i++) {
								prevCmd[i] = buff[i];
							}
						}
						buff = new byte[1024];
					}
				} catch (Exception e) {
				}
			});

			if (!isTtyEnabled && isOpenStdin) {
				t_in.start();
			}
		} catch (Exception e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@SuppressWarnings("unused")
	public List<ContainerFileProxy> readContainerDirectory(final String id,
			final String path) throws DockerException {
		List<ContainerFileProxy> childList = new ArrayList<>();
		try {
			DockerClient copyClient = getClientCopy();
			final String execId = copyClient.execCreate(id,
					new String[] { "/bin/sh", "-c", "ls -l -F -L -Q " + path }, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
					ExecCreateParam.attachStdout(),
					ExecCreateParam.attachStderr());
			final LogStream pty_stream = copyClient.execStart(execId);
			try {
				while (pty_stream.hasNext()) {
					ByteBuffer b = pty_stream.next().content();
					byte[] buffer = new byte[b.remaining()];
					b.get(buffer);
					String s = new String(buffer);
					String[] lines = s.split("\\r?\\n"); //$NON-NLS-1$
					for (String line : lines) {
						if (line.trim().startsWith("total")) //$NON-NLS-1$
							continue; // ignore the total line
						String[] token = line.split("\\s+"); //$NON-NLS-1$
						boolean isDirectory = token[0].startsWith("d"); //$NON-NLS-1$
						boolean isLink = token[0].startsWith("l"); //$NON-NLS-1$
						if (token.length > 8) {
							// last token depends on whether we have a link or not
							String link = null;
							if (isLink) {
								String linkname = token[token.length - 1];
								if (linkname.endsWith("/")) { //$NON-NLS-1$
									linkname = linkname.substring(0, linkname.length() - 1);
									isDirectory = true;
								}
								IPath linkPath = new Path(path);
								linkPath = linkPath.append(linkname);
								link = linkPath.toString();
								String name = token[token.length - 3];
								childList.add(new ContainerFileProxy(path, name,
										isDirectory, isLink, link));
							} else {
								String name = token[token.length - 1];
								// remove quotes and any indicator char
								name = name.substring(1, name.length()
										- (name.endsWith("\"") ? 1 : 2));
								childList.add(new ContainerFileProxy(path, name,
										isDirectory));
							}
						}
					}
				}
			} finally {
				if (pty_stream != null)
					pty_stream.close();
				if (copyClient != null)
					copyClient.close();
			}
		} catch (Exception e) {
			// e.printStackTrace();
		}
		return childList;
	}

	public void execShell(final String id) throws DockerException {
		try {
			final String execId = client.execCreate(id,
					new String[] { "/bin/sh" }, //$NON-NLS-1$
					ExecCreateParam.attachStdout(),
					ExecCreateParam.attachStderr(),
					ExecCreateParam.attachStdin(),
					ExecCreateParam.tty());

			final LogStream pty_stream = client.execStart(execId,
					DockerClient.ExecStartParameter.TTY);
			final IDockerContainerInfo info = getContainerInfo(id);
			openTerminal(pty_stream, info.name() + " [shell]"); //$NON-NLS-1$
		} catch (Exception e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	private void openTerminal(LogStream pty_stream, String name) throws DockerException {
		try {
			OutputStream tout = noBlockingOutputStream(HttpHijackWorkaround.getOutputStream(pty_stream, getUri()));
			InputStream tin = HttpHijackWorkaround.getInputStream(pty_stream);
			// org.eclipse.tm.terminal.connector.ssh.controls.SshWizardConfigurationPanel
			Map<String, Object> properties = new HashMap<>();
			properties.put(ITerminalsConnectorConstants.PROP_DELEGATE_ID,
					"org.eclipse.tm.terminal.connector.streams.launcher.streams"); //$NON-NLS-1$
			properties.put(
					ITerminalsConnectorConstants.PROP_TERMINAL_CONNECTOR_ID,
					"org.eclipse.tm.terminal.connector.streams.StreamsConnector"); //$NON-NLS-1$
			properties.put(ITerminalsConnectorConstants.PROP_TITLE, name);
			properties.put(ITerminalsConnectorConstants.PROP_LOCAL_ECHO, false);
			properties.put(ITerminalsConnectorConstants.PROP_FORCE_NEW, true);
			properties.put(ITerminalsConnectorConstants.PROP_STREAMS_STDIN, tout);
			properties.put(ITerminalsConnectorConstants.PROP_STREAMS_STDOUT, tin);
			properties.put(ITerminalsConnectorConstants.PROP_DATA, pty_stream);
			/*
			 * The JVM will call finalize() on 'pty_stream' (LogStream)
			 * since we hold no references to it (although we do hold
			 * references to one of its heavily nested fields. The
			 * LogStream overrides finalize() to close the stream being
			 * used so we must preserve a reference to it.
			 */
			properties.put("PREVENT_JVM_GC_FINALIZE", pty_stream); //$NON-NLS-1$
			ITerminalService service = TerminalServiceFactory.getService();
			service.openConsole(properties, null);
		} catch (Exception e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public String getTcpCertPath() {
		if (this.connectionSettings.getType() == BindingType.TCP_CONNECTION) {
			return ((TCPConnectionSettings) this.connectionSettings)
					.getPathToCertificates();
		}
		return null;
	}

	@Override
	public String toString() {
		return name;
	}

	public static OutputStream noBlockingOutputStream(final WritableByteChannel out) {
		return new OutputStream() {

			@Override
			public synchronized void write(int i) throws IOException {
				byte b[] = new byte[1];
				b[0] = (byte) i;
				write(b);
			}

			@Override
			public synchronized void write(byte[] b, int off, int len)
					throws IOException {
				if (len == 0) {
					return;
				}
				ByteBuffer buff = ByteBuffer.wrap(b, off, len);
				while (buff.remaining() > 0) {
					out.write(buff);
				}
			}

			@Override
			public void close() throws IOException {
				out.close();
			}
		};
	}

	@Override
	public IDockerNetworkCreation createNetwork(IDockerNetworkConfig cfg)
			throws DockerException, InterruptedException {
		try {
			Ipam.Builder ipamBuilder = Ipam.builder()
					.driver(cfg.ipam().driver());
			List<IDockerIpamConfig> ipamCfgs = cfg.ipam().config();
			for (IDockerIpamConfig ipamCfg : ipamCfgs) {
				ipamBuilder = ipamBuilder.config(ipamCfg.subnet(),
						ipamCfg.ipRange(), ipamCfg.gateway());
			}
			Ipam ipam = ipamBuilder.build();
			NetworkConfig.Builder networkConfigBuilder = NetworkConfig.builder()
					.name(cfg.name()).driver(cfg.driver()).ipam(ipam);
			Map<String, String> cfgOptions = cfg.options();
			for (Entry<String, String> entry : cfgOptions.entrySet()) {
				networkConfigBuilder.option(entry.getKey(), entry.getValue());
			}
			NetworkConfig networkConfig = networkConfigBuilder.build();
			com.spotify.docker.client.messages.NetworkCreation creation = client
					.createNetwork(networkConfig);
			return new DockerNetworkCreation(creation);

		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public IDockerNetwork inspectNetwork(String networkId)
			throws DockerException, InterruptedException {
		try {
			Network n = client.inspectNetwork(networkId);
			return new DockerNetwork(n);
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public List<IDockerNetwork> listNetworks()
			throws DockerException, InterruptedException {
		try {
			List<Network> networkList = client.listNetworks();
			ArrayList<IDockerNetwork> networks = new ArrayList<>();
			for (Network n : networkList) {
				networks.add(new DockerNetwork(n));
			}
			return networks;
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public void removeNetwork(String networkId)
			throws DockerException, InterruptedException {
		try {
			client.removeNetwork(networkId);
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public void connectNetwork(String id, String networkId)
			throws DockerException, InterruptedException {
		try {
			client.connectToNetwork(id, networkId);
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public void disconnectNetwork(String id, String networkId)
			throws DockerException, InterruptedException {
		try {
			client.disconnectFromNetwork(id, networkId);
		} catch (com.spotify.docker.client.DockerException e) {
			throw new DockerException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public boolean equals(Object other) {
		if (other instanceof IDockerConnection) {
			return getSettings()
					.equals(((IDockerConnection) other).getSettings());
		}
		return false;
	}

	@Override
	public int hashCode() {
		return getSettings().hashCode();
	}

	@Override
	public IDockerImageHierarchyNode resolveImageHierarchy(
			final IDockerImage selectedImage) {
		return DockerImageHierarchyNodeUtils.resolveImageHierarchy(this.images,
				this.containers, selectedImage);
	}

	@Override
	public IDockerImageHierarchyNode resolveImageHierarchy(
			final IDockerContainer selectedContainer) {
		return DockerImageHierarchyNodeUtils.resolveImageHierarchy(this.images,
				selectedContainer);
	}

}
