/******************************************************************************* * Copyright (c) 2014, 2017 Red Hat. * 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.docker.core; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import org.eclipse.core.runtime.ListenerList; import org.eclipse.linuxtools.docker.core.IDockerConnectionSettings.BindingType; import org.eclipse.linuxtools.internal.docker.core.DefaultDockerConnectionSettingsFinder; import org.eclipse.linuxtools.internal.docker.core.DefaultDockerConnectionStorageManager; import org.eclipse.linuxtools.internal.docker.core.DockerConnection; import org.eclipse.linuxtools.internal.docker.core.DockerContainerRefreshManager; import org.eclipse.linuxtools.internal.docker.core.TCPConnectionSettings; import org.eclipse.linuxtools.internal.docker.core.UnixSocketConnectionSettings; public class DockerConnectionManager { private static DockerConnectionManager instance; private List<IDockerConnection> connections; private ListenerList<IDockerConnectionManagerListener> connectionManagerListeners; private IDockerConnectionSettingsFinder connectionSettingsFinder = new DefaultDockerConnectionSettingsFinder(); private IDockerConnectionStorageManager connectionStorageManager = new DefaultDockerConnectionStorageManager(); public static DockerConnectionManager getInstance() { if (instance == null) { instance = new DockerConnectionManager(); } return instance; } private DockerConnectionManager() { reloadConnections(); } public void reloadConnections() { this.connections = connectionStorageManager.loadConnections(); for (IDockerConnection connection : connections) { notifyListeners(connection, IDockerConnectionManagerListener.ADD_EVENT); } List<IDockerConnectionSettings> settings = connectionSettingsFinder .getKnownConnectionSettings(); for (IDockerConnectionSettings setting : settings) { if (setting != null) { IDockerConnection conn; if (setting.getType().equals(BindingType.UNIX_SOCKET_CONNECTION)) { UnixSocketConnectionSettings usetting = (UnixSocketConnectionSettings) setting; conn = new DockerConnection.Builder().name(usetting.getName()) .unixSocketConnection(usetting); } else { TCPConnectionSettings tsetting = (TCPConnectionSettings) setting; conn = new DockerConnection.Builder().name(tsetting.getName()) .tcpConnection(tsetting); } // add the connection but do not notify the listeners to avoid // flickering on the Docker Explorer view for each entry addConnection(conn, false); } } } public void setConnectionSettingsFinder( final IDockerConnectionSettingsFinder connectionSettingsFinder) { this.connectionSettingsFinder = connectionSettingsFinder; } public void setConnectionStorageManager( final IDockerConnectionStorageManager connectionStorageManager) { this.connectionStorageManager = connectionStorageManager; } public void saveConnections() { this.connectionStorageManager.saveConnections(this.connections); } /** * @return an unmodifiable and non-null array of {@link IDockerConnection} */ public IDockerConnection[] getConnections() { if (this.connections == null) { return new IDockerConnection[0]; } return connections.toArray(new IDockerConnection[connections.size()]); } /** * @return an unmodifiable and non-null list of {@link IDockerConnection} */ public List<IDockerConnection> getAllConnections() { if (this.connections == null) { return Collections.emptyList(); } return Collections.unmodifiableList(this.connections); } /** * @return the first {@link IDockerConnection} or <code>null</code> if none * exists yet. */ public IDockerConnection getFirstConnection() { if (!hasConnections()) { return null; } return this.connections.get(0); } /** * @return <code>true</code> if there is at least one * {@link IDockerConnection} in this * {@link DockerConnectionManager}, <code>false</code> otherwise. */ public boolean hasConnections() { return connections != null && !connections.isEmpty(); } /** * Finds the {@link IDockerConnection} from the given {@code connectionName} * * @param connectionName * the name of the connection to find * @return the {@link IDockerConnection} or <code>null</code> if none * matched. */ public IDockerConnection getConnectionByName(final String connectionName) { return this.connections.stream().filter( connection -> connection.getName().equals(connectionName)) .findFirst().orElse(null); } /** * Finds the {@link IDockerConnection} from the given {@code connectionUri} * * @param connectionUri * the URI of the connection to find * @return the {@link IDockerConnection} or <code>null</code> if none * matched. */ public IDockerConnection getConnectionByUri(String connectionUri) { return DockerConnectionManager.getInstance().getAllConnections() .stream() .filter(c -> c.getUri().equals(connectionUri)).findFirst() .orElse(null); } /** * @return an immutable {@link List} of the {@link IDockerConnection} names */ public List<String> getConnectionNames() { return Collections.unmodifiableList(getAllConnections().stream() .map(c -> c.getName()) // making sure that no 'null' name is returned in the list of // connection names. .filter(n -> n != null) .collect(Collectors.toList())); } public IDockerConnection findConnection(final String name) { if (name != null) { for (IDockerConnection connection : connections) { if (connection.getName() != null && connection.getName().equals(name)) return connection; } } return null; } /** * Adds the given connection and notifies all registered * {@link IDockerConnectionManagerListener} * * @param dockerConnection * the connection to add */ public void addConnection(final IDockerConnection dockerConnection) { addConnection(dockerConnection, true); } /** * Adds the given connection and notifies optionally all registered * {@link IDockerConnectionManagerListener} * * @param dockerConnection * the connection to add * @param notifyListeners * flag to indicate if registered * {@link IDockerConnectionManagerListener} should be notified * about the {@link IDockerConnection} addition. */ public void addConnection(final IDockerConnection dockerConnection, final boolean notifyListeners) { if (!connections.contains(dockerConnection)) { connections.add(dockerConnection); saveConnections(); if (notifyListeners) { notifyListeners(dockerConnection, IDockerConnectionManagerListener.ADD_EVENT); } } } public void removeConnection(final IDockerConnection connection) { connections.remove(connection); saveConnections(); notifyListeners(connection, IDockerConnectionManagerListener.REMOVE_EVENT); DockerContainerRefreshManager.getInstance() .removeContainerRefreshThread(connection); } public void addConnectionManagerListener( IDockerConnectionManagerListener listener) { if (connectionManagerListeners == null) connectionManagerListeners = new ListenerList<>( ListenerList.IDENTITY); connectionManagerListeners.add(listener); } public void removeConnectionManagerListener( IDockerConnectionManagerListener listener) { if (connectionManagerListeners != null) connectionManagerListeners.remove(listener); } /** * Notifies all listeners that a change occurred on the given connection * * @param connection * the connection that changed * @param type * the type of change */ public void notifyListeners(final IDockerConnection connection, final int type) { if (connectionManagerListeners != null) { for (IDockerConnectionManagerListener listener : connectionManagerListeners) { listener.changeEvent(connection, type); } } } /** * Finds the default {@link IDockerConnectionSettings} * * @return the default {@link IDockerConnectionSettings} or * <code>null</code> if nothing was found */ public IDockerConnectionSettings findDefaultConnectionSettings() { // delegate the call to a utility class. return connectionSettingsFinder.findDefaultConnectionSettings(); } /** * Resolves the name of the Docker instance, given the * {@link IDockerConnectionSettings} * * @param connectionSettings * the settings to use to connect * @return the name retrieved from the Docker instance or <code>null</code> * if something went wrong. */ public String resolveConnectionName( IDockerConnectionSettings connectionSettings) { return connectionSettingsFinder .resolveConnectionName(connectionSettings); } /** * Updates the given {@link IDockerConnection} with the given {@code name} * and {@code connectionSettings} * * @param connection * the {@link IDockerConnection} to update * @param name * the (new) connection name * @param connectionSettings * the (new) connection settings * @return <code>true</code> if the connection name or settings changed, * <code>false</code> otherwise. */ public boolean updateConnection(final IDockerConnection connection, final String name, final IDockerConnectionSettings connectionSettings) { final boolean nameChanged = connection.setName(name); final boolean settingsChanged = connection .setSettings(connectionSettings); if (nameChanged) { notifyListeners(connection, IDockerConnectionManagerListener.RENAME_EVENT); } if (settingsChanged) { notifyListeners(connection, IDockerConnectionManagerListener.UPDATE_SETTINGS_EVENT); } if (nameChanged || settingsChanged) { saveConnections(); return true; } return false; } }