Skip to content

Commit

Permalink
JBIDE-21170 - issue finding vagrant in mac when launched via .app
Browse files Browse the repository at this point in the history
Cleanup of API and giving mac the default assumption that the system path is more accurate

Ensure that even our which command also has the system path available, or else which won't be able to find it
  • Loading branch information
robstryker committed Mar 2, 2016
1 parent 4712105 commit 2b7e853
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugEvent;
Expand Down Expand Up @@ -49,6 +50,7 @@
import org.jboss.tools.openshift.cdk.server.core.internal.adapter.CDKServerBehaviour;
import org.jboss.tools.openshift.cdk.server.core.internal.adapter.VagrantPoller;
import org.jboss.tools.openshift.cdk.server.ui.internal.util.TerminalUtility;
import org.jboss.tools.openshift.internal.common.core.util.CommandLocationLookupStrategy;

public class CDKLaunchController extends AbstractSubsystemController implements ILaunchServerController, IExternalLaunchConstants {
private static final String FLAG_INITIALIZED = "org.jboss.tools.openshift.cdk.server.core.internal.adapter.controllers.launch.isInitialized";
Expand Down Expand Up @@ -88,6 +90,13 @@ private void performOverrides(ILaunchConfigurationWorkingCopy workingCopy) throw
String userKey = cdkServer.getServer().getAttribute(CDKServer.PROP_USER_ENV_VAR, CDKConstants.CDK_ENV_SUB_USERNAME);
env.put(userKey, cdkServer.getUsername());
}

String vLoc = CDKConstantUtility.getVagrantLocation();
if( vLoc != null ) {
String vagrantCmdFolder = new Path(vLoc).removeLastSegments(1).toOSString();
CommandLocationLookupStrategy.get().ensureOnPath(env, vagrantCmdFolder);
}

if( Platform.getOS().equals(Platform.OS_WIN32)) {
// We need to set the cygwin flag
env.put("VAGRANT_DETECTED_OS", "cygwin");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2016 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.openshift.cdk.server.core.internal.adapter.controllers;

import static org.jboss.tools.openshift.cdk.server.core.internal.adapter.controllers.IExternalLaunchConstants.ATTR_ARGS;
Expand All @@ -9,26 +19,27 @@
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeoutException;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.wst.server.core.IServer;
import org.jboss.tools.openshift.cdk.server.core.internal.CDKConstantUtility;
import org.jboss.tools.openshift.cdk.server.core.internal.CDKConstants;
import org.jboss.tools.openshift.cdk.server.core.internal.CDKCoreActivator;
import org.jboss.tools.openshift.cdk.server.core.internal.adapter.CDKServer;
import org.jboss.tools.openshift.internal.common.core.util.CommandLocationLookupStrategy;
import org.jboss.tools.openshift.internal.common.core.util.ThreadUtils;

public class VagrantLaunchUtility {
Expand Down Expand Up @@ -124,10 +135,14 @@ public static String[] call(String rootCommand, String[] args, File vagrantDir,
throws IOException, TimeoutException {
return call(rootCommand, args, vagrantDir, env, 30000);
}


private static void ensureCommandOnPath(String rootCommand, Map<String, String> env) {
CommandLocationLookupStrategy.get().ensureOnPath(env, new Path(rootCommand).removeLastSegments(1).toOSString());
}

public static String[] call(String rootCommand, String[] args, File vagrantDir, Map<String, String> env,
int timeout) throws IOException, TimeoutException {

ensureCommandOnPath(rootCommand, env);
String[] envp = (env == null ? null : convertEnvironment(env));

List<String> cmd = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,54 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

import org.apache.commons.lang.StringUtils;
import org.eclipse.core.runtime.Platform;
import org.jboss.tools.openshift.internal.common.core.OpenShiftCommonCoreActivator;

public class CommandLocationLookupStrategy {
private static final String LINUX_WHICH = "which ";
private static final String WINDOWS_WHERE = "where ";
private static final String LINUX_WHICH = "which";
private static final String WINDOWS_WHERE = "where";
private static final String LINUX_PATHVAR = "PATH";
private static final String WINDOWS_PATHVAR = "Path";

public static final CommandLocationLookupStrategy WINDOWS_STRATEGY =
new CommandLocationLookupStrategy(WINDOWS_WHERE, ";", WINDOWS_PATHVAR, new String[]{".exe", ".com"});
new CommandLocationLookupStrategy(WINDOWS_WHERE, ";", WINDOWS_PATHVAR, new String[]{".exe", ".com"}, null);
public static final CommandLocationLookupStrategy LINUX_STRATEGY =
new CommandLocationLookupStrategy(LINUX_WHICH, ":", LINUX_PATHVAR, new String[]{});
new CommandLocationLookupStrategy(LINUX_WHICH, ":", LINUX_PATHVAR, new String[]{}, null);
public static final CommandLocationLookupStrategy MAC_STRATEGY =
new CommandLocationLookupStrategy(LINUX_WHICH, ":", LINUX_PATHVAR, new String[]{}, new String[]{"bash", "-l", "-i", "-c", "echo $PATH"}, true);

public static CommandLocationLookupStrategy get() {
String os = Platform.getOS();
if( Platform.OS_WIN32.equals(os)) {
return WINDOWS_STRATEGY;
}
if( Platform.OS_MACOSX.equals(os)) {
return MAC_STRATEGY;
}
return LINUX_STRATEGY;
}

private String which, delim, pathvar;
private String[] pathCommand;
private String[] suffixes;
public CommandLocationLookupStrategy(String which, String delim, String pathvar, String[] suffixes) {
private boolean preferSystemPath;
public CommandLocationLookupStrategy(String which, String delim, String pathvar, String[] suffixes, String[] pathCommand) {
this(which, delim, pathvar, suffixes, pathCommand, false);
}

public CommandLocationLookupStrategy(String which, String delim, String pathvar, String[] suffixes, String[] pathCommand, boolean preferSystemPath) {
this.which = which;
this.delim = delim;
this.pathvar = pathvar;
this.suffixes = suffixes;
this.pathCommand = pathCommand;
this.preferSystemPath = preferSystemPath;
}

public String search(CommandLocationBinary binary) {
Expand Down Expand Up @@ -82,11 +99,57 @@ private String findLocation(String defaultLoc, String cmd, String which, String
}
String ret = searchPath(System.getenv(pathvar), delim, cmd);
if( ret == null ) {
ret = runCommand(which + cmd, timeout);
// run which / where
ret = runCommandAndVerify(new String[]{which, cmd}, timeout);
}
return ret;
}



/**
* Ensure the given folder is on the path in the provided environment map,
* or append to existing path in provided environment.
*
* If the provided environment has no path variable, fetch an environment from
* either the currently running environment (if preferSystemPath is false) or
* from the system via pathCommand member variable) if preferSystemPath is true.
*
* @param env
* @param folder
*/
public void ensureOnPath( Map<String, String> env, String folder) {
HashMap<String,String> processEnv = new HashMap<String,String>(System.getenv());
if( env.get(pathvar) == null ) {
if( preferSystemPath ) {
String pathresult = runCommand(pathCommand);
processEnv.put(pathvar, pathresult);
}
String newPath = ensureFolderOnPath(processEnv.get(pathvar), folder);
env.put(pathvar, newPath);
} else {
String newPath = ensureFolderOnPath(env.get(pathvar), folder);
env.put(pathvar, newPath);
}
}

/**
* Append the given folder to the existing path if not already present
*
* @param existingPath
* @param folder
* @return
*/
private String ensureFolderOnPath(String existingPath, String folder) {
existingPath = (existingPath == null ? "" : existingPath);
String[] roots = existingPath.split(delim);
ArrayList<String> list = new ArrayList<String>(Arrays.asList(roots));
if( !list.contains(folder)) {
list.add(folder);
}
return String.join(delim, list);
}

/**
* Get all possible command names by appending the various suffixes to the command name
* @param commandName
Expand Down Expand Up @@ -114,47 +177,110 @@ private String searchPath(String path, String delim, String commandName) {
}
return null;
}

private String runCommand(final String cmd, int timeout) {
private String runCommandAndVerify(final String[] cmd, int timeout) {
if( timeout == -1 ) {
return runCommand(cmd);
return runCommandAndVerify(cmd);
} else {
String path = ThreadUtils.runWithTimeout(timeout, new Callable<String>() {
@Override
public String call() throws Exception {
return runCommand(cmd);
return runCommandAndVerify(cmd);
}
});
return path;
}
}

private String runCommand(String cmd) {
private String runCommandAndVerify(String[] cmd) {
Process p = createProcess(cmd, preferSystemPath);
if( p != null ) {
String result = readProcess(p);
// verify the output is a file path that exists
if( result != null && !result.isEmpty() && new File(result).exists())
return result;
}
return null;
}

private String runCommand(String cmd[]) {
Process p = createProcess(cmd);
if( p != null ) {
String result = readProcess(p);
return result;
}
return null;
}

/**
* Use runtime.exec(String[]) to run a command.
* This method *does not* respect the preferSystemPath member variable
* and will run with whatever the default environment is.
*
* @param cmd
* @return
*/
private Process createProcess(String cmd[]) {
try {
return Runtime.getRuntime().exec(cmd);
} catch(IOException ioe) {
OpenShiftCommonCoreActivator.log(ioe);
return null;
}
}

/**
* Use runtime.exec(String)
* @param cmd
* @return
*/
private Process createProcess(String[] cmd, boolean useSystemPath) {
try {
if( useSystemPath) {
String pathresult = runCommand(pathCommand);
ProcessBuilder pb = new ProcessBuilder(cmd);
Map<String,String> env = pb.environment();
env.put(pathvar, pathresult);
return pb.start();
} else {
return Runtime.getRuntime().exec(cmd);
}
} catch(IOException ioe) {
OpenShiftCommonCoreActivator.log(ioe);
return null;
}
}

Process p = null;

private String readProcess(Process p) {
try {
p = Runtime.getRuntime().exec(cmd);
p.waitFor();
} catch(InterruptedException ie) {
// Ignore, expected
}
InputStream is = null;
if(p.exitValue() == 0) {
is = p.getInputStream();
} else {
// For debugging only
//is = p.getErrorStream();
}
if( is != null ) {
try {
p.waitFor();
} catch(InterruptedException ie) {
// Ignore, expected
}
if(p.exitValue() == 0) {
InputStream is = p.getInputStream();
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
String cmdOutput = s.hasNext() ? s.next() : "";
if( !cmdOutput.isEmpty()) {
cmdOutput = StringUtils.trim(cmdOutput);
if( new File(cmdOutput).exists())
return cmdOutput;
return cmdOutput;
}
} finally {
try {
if( p != null ) {
p.destroy();
}
is.close();
} catch(IOException ioe) {
// ignore
}
}

} catch(IOException ioe) {
// Ignore this
} finally {
if( p != null ) {
p.destroy();
}
}
return null;
Expand Down

0 comments on commit 2b7e853

Please sign in to comment.