/******************************************************************************* * Copyright (c) 2016 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.internal.docker.core; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Properties; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.linuxtools.docker.core.Activator; import org.eclipse.linuxtools.docker.core.IDockerConnectionSettings; import org.eclipse.linuxtools.docker.core.IDockerConnectionSettingsProvider; import org.eclipse.linuxtools.docker.core.Messages; public class ShellConnectionSettingsProvider implements IDockerConnectionSettingsProvider { @Override public List<IDockerConnectionSettings> getConnectionSettings() { try { final String connectionSettingsDetectionScriptName = getConnectionSettingsDetectionScriptName(); if (connectionSettingsDetectionScriptName == null) { Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.Docker_No_Settings_Description_Script)); return Collections.emptyList(); } final File connectionSettingsDetectionScript = getConnectionSettingsDetectionScript( connectionSettingsDetectionScriptName); final String[] cmdArray = getConnectionSettingsDetectionCommandArray( connectionSettingsDetectionScript); final Process process = Runtime.getRuntime().exec(cmdArray); process.waitFor(); final int exitValue = process.exitValue(); if (exitValue == 0) { final InputStream processInputStream = process.getInputStream(); // read content from process input stream final Properties dockerSettings = new Properties(); dockerSettings.load(processInputStream); IDockerConnectionSettings setting = createDockerConnectionSettings(dockerSettings); if (setting == null) { return Collections.emptyList(); } return Arrays.asList(setting); } else { // log what happened if the process did not end as expected // an exit value of 1 should indicate no connection found if (exitValue != 1) { final InputStream processErrorStream = process .getErrorStream(); final String errorMessage = streamToString( processErrorStream); Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, errorMessage)); } } } catch (IOException | IllegalArgumentException | InterruptedException e) { Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.Retrieve_Default_Settings_Failure, e)); } return Collections.emptyList(); } /** * @param script * the script to execute * @return the OS-specific command to run the connection settings detection * script or <code>null</code> if the current OS is not supported. */ private String[] getConnectionSettingsDetectionCommandArray( final File script) { if (Platform.getOS().equals(Platform.OS_WIN32)) { return new String[] { "cmd.exe", "/C", //$NON-NLS-1$ //$NON-NLS-2$ script.getAbsolutePath() }; } else { return new String[] { script.getAbsolutePath() }; } } /** * Finds the script file in the data directory of the bundle given its name, * or creates it from the 'resources' dir in the bundle if it was not found * in the data dir. * * @param scriptName * the name of the script to load in the data dir or in the * 'resources' dir in the bundle * @return the script {@link File} */ private File getConnectionSettingsDetectionScript(final String scriptName) { final File script = Activator.getDefault().getBundle() .getDataFile(scriptName); // if the script file does not exist or is outdated. if (script != null && (!script.exists() || script.lastModified() < Activator .getDefault().getBundle().getLastModified())) { try (final FileOutputStream output = new FileOutputStream(script); final InputStream is = DockerConnection.class .getResourceAsStream("/resources/" + scriptName)) { //$NON-NLS-1$ byte[] buff = new byte[1024]; int n; while ((n = is.read(buff)) > 0) { output.write(buff, 0, n); } script.setExecutable(true); } catch (IOException e) { Activator.logErrorMessage(ProcessMessages .getString("Settings_Detection_Exception"), e); //$NON-NLS-1$ } } return script; } /** * @return the name of the script to run, depending on the OS (Windows, MAc, * *Nix) or <code>null</code> if the current OS is not supported. */ private String getConnectionSettingsDetectionScriptName() { if (SystemUtils.isLinux()) { return "script.sh";//$NON-NLS-1$ } else if (SystemUtils.isMac()) { return "script-macosx.sh";//$NON-NLS-1$ } else if (SystemUtils.isWindows()) { return "script.bat"; //$NON-NLS-1$ } return null; } private String streamToString(InputStream stream) { BufferedReader buff = new BufferedReader(new InputStreamReader(stream)); StringBuffer res = new StringBuffer(); String line = ""; //$NON-NLS-1$ try { while ((line = buff.readLine()) != null) { res.append(System.getProperty("line.separator")); //$NON-NLS-1$ res.append(line); } buff.close(); } catch (IOException e) { } return res.length() > 0 ? res.substring(1) : ""; } /** * Creates connection settings from the given {@code docerSettings}, or * <code>null</code> if the settings did not contain a property with the * {@code DOCKER_HOST} key. * * @param dockerSettings * the connection settings * @return the {@link IDockerConnectionSettings} or <code>null</code> if the * settings are invalid. */ public static IDockerConnectionSettings createDockerConnectionSettings( final Properties dockerSettings) { final Object dockerHostEnvVariable = dockerSettings .get(DefaultDockerConnectionSettingsFinder.DOCKER_HOST); final Object dockerCertPathEnvVariable = dockerSettings .get(DefaultDockerConnectionSettingsFinder.DOCKER_CERT_PATH); // at least 'dockerHostEnvVariable' should be not null if (dockerHostEnvVariable == null) { return null; } return new TCPConnectionSettings(dockerHostEnvVariable.toString(), dockerCertPathEnvVariable != null ? dockerCertPathEnvVariable.toString() : null); } }