com.amazonaws.eclipse.ec2.PlatformUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.amazonaws.eclipse.ec2.PlatformUtils.java

Source

/*
 * Copyright 2008-2011 Amazon Technologies, Inc. 
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at:
 * 
 *    http://aws.amazon.com/apache2.0
 *
 * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 
 * OR CONDITIONS OF ANY KIND, either express or implied. See the 
 * License for the specific language governing permissions and 
 * limitations under the License. 
 */

package com.amazonaws.eclipse.ec2;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.logging.Logger;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.statushandlers.StatusManager;

import com.amazonaws.eclipse.ec2.preferences.PreferenceConstants;

/**
 * Basic utilities for working with platform differences.
 */
public class PlatformUtils {

    private static final String PPK_CONVERTER_EXE = "/bin/PemToPPKConverter.exe";
    private static final Logger logger = Logger.getLogger(PlatformUtils.class.getName());

    /**
     * Returns true if the current platform is a windows platform.
     * 
     * @return True if the current platform is a windows platform.
     */
    public boolean isWindows() {
        String platform = System.getProperty("os.name");

        if (platform == null) {
            Status status = new Status(IStatus.WARNING, Ec2Plugin.PLUGIN_ID, "No system property for 'os.name'");
            StatusManager.getManager().handle(status, StatusManager.LOG);

            return false;
        }

        return platform.toLowerCase().contains("windows");
    }

    /**
     * Returns true if the current platform is a Linux platform.
     * 
     * @return True if the current platform is a Linux platform.
     */
    public boolean isLinux() {
        String platform = System.getProperty("os.name");

        if (platform == null) {
            Status status = new Status(IStatus.WARNING, Ec2Plugin.PLUGIN_ID, "No system property for 'os.name'");
            StatusManager.getManager().handle(status, StatusManager.LOG);

            return false;
        }

        return platform.toLowerCase().contains("linux");
    }

    /**
     * Returns true if the current platform is a Mac platform.
     * 
     * @return True if the current platform is a Mac platform.
     */
    public boolean isMac() {
        String platform = System.getProperty("os.name");

        if (platform == null) {
            Status status = new Status(IStatus.WARNING, Ec2Plugin.PLUGIN_ID, "No system property for 'os.name'");
            StatusManager.getManager().handle(status, StatusManager.LOG);

            return false;
        }

        return platform.toLowerCase().contains("mac os");
    }

    /**
     * Returns true if the platform specific SSH client is correctly configured
     * and ready to be used on this system.
     * 
     * @return True if the platform specific SSH client is correctly configured
     *         and ready to be used on this system.
     */
    public boolean isSshClientConfigured() {
        if (isWindows()) {
            String puttyPath = Ec2Plugin.getDefault().getPreferenceStore()
                    .getString(PreferenceConstants.P_PUTTY_EXECUTABLE);

            // First make sure something is specified...
            if (puttyPath == null || puttyPath.length() == 0)
                return false;

            // Next make sure it's a file
            if (!new File(puttyPath).isFile())
                return false;
        }

        return true;
    }

    /**
     * Opens a shell to the specified host using a platform specific terminal
     * window.
     * 
     * @param user
     *            The user to connect to the remote host as.
     * @param host
     *            The remote host to connect to.
     * @param identityFile
     *            The file containing the identity file for the connection.
     * @throws IOException
     *             If any problems are encountered opening the remote shell.
     */
    public void openShellToRemoteHost(String user, String host, String identityFile)
            throws IOException, InterruptedException, URISyntaxException {

        IPreferenceStore preferenceStore = Ec2Plugin.getDefault().getPreferenceStore();

        String sshOptions = preferenceStore.getString(PreferenceConstants.P_SSH_OPTIONS);
        String sshCommand = preferenceStore.getString(PreferenceConstants.P_SSH_CLIENT);
        sshCommand += " " + sshOptions + " -i " + identityFile + " " + user + "@" + host;

        if (isMac()) {
            URL locationUrl = FileLocator.find(Ec2Plugin.getDefault().getBundle(), new Path("/"), null);
            URL fileUrl = FileLocator.toFileURL(locationUrl);
            executeAsynchronousCommand(new String[] { "osascript",
                    fileUrl.getFile() + "scripts/openMacTerminalShell.scpt", sshCommand });
        } else if (isLinux()) {
            String terminalCommand = preferenceStore.getString(PreferenceConstants.P_TERMINAL_EXECUTABLE);

            executeAsynchronousCommand(new String[] { terminalCommand, "-e", sshCommand });
        } else if (isWindows()) {
            openRemoteShellFromWindows(user, host, identityFile);
        } else {
            String osName = System.getProperty("os.name");

            Status status = new Status(IStatus.ERROR, Ec2Plugin.PLUGIN_ID,
                    "Unable to determine what platform '" + osName + "' is.");
            StatusManager.getManager().handle(status, StatusManager.SHOW | StatusManager.LOG);
        }
    }

    /*
     * Private Interface
     */

    /**
     * Opens a remote shell connection from a windows host as the specified user
     * to the specified host using the OpenSSH identity file to authenticate.
     * This method assumes that the user has already configured their SSH tools
     * (PuTTY), so it doesn't check for that, but it does check to see if the
     * required PuTTY private key exists, and if it doesn't, it will convert it.
     * 
     * @param user
     *            The user to log into the remote host as.
     * @param host
     *            The host to connect to.
     * @param identityFile
     *            The OpenSSH private key file that provides the user
     *            passwordless access to the specified host.
     * @throws IOException
     *             If any problems are encountered executing the SSH client.
     */
    private void openRemoteShellFromWindows(String user, String host, String identityFile)
            throws IOException, InterruptedException, URISyntaxException {
        String puttyExecutable = Ec2Plugin.getDefault().getPreferenceStore()
                .getString(PreferenceConstants.P_PUTTY_EXECUTABLE);

        File privateKeyFile = new File(identityFile);
        if (!privateKeyFile.isFile()) {
            throw new IOException("Unable to find the required OpenSSH private key '" + identityFile + "'.");
        }

        String puttyPrivateKeyFile = translateOpenSshPrivateKeyFileToPuttyPrivateKeyFile(identityFile);

        File ppkFile = new File(puttyPrivateKeyFile);
        if (!ppkFile.exists()) {
            executeAsynchronousCommand(new String[] { getPuttyGenConversionExecutable(), "\"" + identityFile + "\"",
                    "\"" + ppkFile.getAbsolutePath() + "\"" }).waitFor();
        }

        String[] openShellCommand = new String[] { puttyExecutable, "-ssh", "-i", puttyPrivateKeyFile,
                user + "@" + host };
        executeAsynchronousCommand(openShellCommand);
    }

    /**
      * Returns the path to the bundled puttygen conversion utility
     * @throws IOException 
      */
    private String getPuttyGenConversionExecutable() throws URISyntaxException, IOException {
        URL conversionExe = FileLocator
                .resolve(FileLocator.find(Ec2Plugin.getDefault().getBundle(), new Path(PPK_CONVERTER_EXE), null));
        return new File(conversionExe.toURI()).getAbsolutePath();
    }

    /**
    * Translates the full path to an OpenSSH private key file to a full path
    * for the corresponding PuTTY private key file.
    * 
    * @param identityFile
    *            The full path to an OpenSSH private key file.
    * 
    * @return The full path for the corresponding PuTTY private key.
    * 
    * @throws IOException
    *             If any problems were encountered translating the OpenSSH
    *             private key file path.
    */
    private String translateOpenSshPrivateKeyFileToPuttyPrivateKeyFile(String identityFile) throws IOException {
        int suffixIndex = identityFile.lastIndexOf(".");
        if (suffixIndex < 0) {
            throw new IOException("Unable to translate '" + identityFile + "' to a PuTTY private key file path.");
        }

        String puttyPrivateKeyFile = identityFile.substring(0, suffixIndex);
        puttyPrivateKeyFile = puttyPrivateKeyFile + ".ppk";

        return puttyPrivateKeyFile;
    }

    /**
     * Executes the specified command array, but does NOT wait for it to finish,
     * therefore no exit code is returned.
     *
     * @param commandArray
     *            The command array to execute.
     * @throws IOException
     *             If there were any problems kicking off the command.
     */
    public Process executeAsynchronousCommand(String[] commandArray) throws IOException {
        String commandString = "";
        for (String command : commandArray) {
            commandString += command + " ";
        }
        logger.info("Executing: " + commandString);

        return Runtime.getRuntime().exec(commandArray);
    }

}