Bug 563019 - [Robotics, ROS2] Handle unset ROS2 environment variables

- Obtain ros2 location from PATH environment, do not assume that it exists in
  <distribution-root>/bin/ros2 which does not hold if installed from source)

Change-Id: I14b94cf6c620c912438137eff303d643bd2a34da
Signed-off-by: Ansgar Radermacher <ansgar.radermacher@cea.fr>
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/EnvironmentUtils.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/EnvironmentUtils.java
index 9815635..0505683 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/EnvironmentUtils.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/EnvironmentUtils.java
@@ -37,6 +37,8 @@
  */
 public class EnvironmentUtils {
 
+	private static final String PATH = "PATH"; //$NON-NLS-1$
+
 	public static final String ROS_PREFIX = "ROS_"; //$NON-NLS-1$
 
 	public static final String DECLARE_X = "declare -x"; //$NON-NLS-1$
@@ -67,24 +69,23 @@
 	// update the following environment values (and those starting with ROS_)
 	public static final List<String> checkValues = Lists.newArrayList(
 			Ros2Constants.AMENT_PREFIX_PATH,
-			"PATH", //$NON-NLS-1$
+			PATH, // $NON-NLS-1$
 			"LD_LIBRARY_PATH", //$NON-NLS-1$
 			"PYTHONPATH"); //$NON-NLS-1$
 
 	@SuppressWarnings("nls")
 	public static void checkAndApplySetup() {
-		String setupPath = Ros2PreferenceUtils.getRosDistroPath() + "/setup.bash";	 //$NON-NLS-1$
+		String setupPath = Ros2PreferenceUtils.getRosDistroPath() + "/setup.bash"; //$NON-NLS-1$
 		if (new File(setupPath).exists()) {
 			sourceScript(setupPath);
-		}
-		else {
+		} else {
 			final Shell shell = Display.getCurrent().getActiveShell();
 			MessageDialog.openInformation(shell, "ROS setup", String.format( //$NON-NLS-1$
-				"It seems that the ROS2 setup file has not been \"sourced\" (AMENT_PREFIX_PATH is not set)\n" +
-				"Papyrus for Robotics could not find a setup.bash file at the standard location (%s). " +
-				"Please specify the PATH to your ROS2 distribution in the ROS2 preferences.\n" +
-				"=> Window => Preferences => type \"ros\" in filter => set path to ROS2 distribution.",
-				Ros2PreferenceUtils.getRosDistroPath()));
+					"It seems that the ROS2 setup file has not been \"sourced\" (AMENT_PREFIX_PATH is not set)\n" +
+							"Papyrus for Robotics could not find a setup.bash file at the standard location (%s). " +
+							"Please specify the PATH to your ROS2 distribution in the ROS2 preferences.\n" +
+							"=> Window => Preferences => type \"ros\" in filter => set path to ROS2 distribution.",
+					Ros2PreferenceUtils.getRosDistroPath()));
 		}
 	}
 
@@ -144,7 +145,7 @@
 			// Map<String, String> env = EnvironmentUtils.getModifiableEnvironmentMap();
 			while ((line = results.readLine()) != null) {
 				line = line.substring(DECLARE_X.length());
-				String lineArray[] = line.split("=");
+				String lineArray[] = line.split("="); //$NON-NLS-1$
 				if (lineArray.length == 2) {
 					String var = lineArray[0].trim();
 					String value = StringUtils.unquote(lineArray[1]);
@@ -158,4 +159,22 @@
 			Activator.log.error(e);
 		}
 	}
+
+	/**
+	 * Return the executable or null
+	 * 
+	 * @param executable
+	 *            the name of the executable
+	 * @return the absolute path to the executable or null
+	 */
+	public static String getFromPath(final String executable) {
+		String[] pathParts = get(PATH).split(File.pathSeparator);
+		for (String pathPart : pathParts) {
+			File file = new File(pathPart + File.separator + executable);
+			if (file.exists()) {
+				return file.getAbsolutePath();
+			}
+		}
+		return null;
+	}
 }
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/Ros2Constants.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/Ros2Constants.java
index 3fcdf55..e55d902 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/Ros2Constants.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/Ros2Constants.java
@@ -20,6 +20,8 @@
 	public static final String ROS2 = "ros2";
 
 	// ros2 message command option
+	public static final String PKG = "pkg";
+	// ros2 service command option
 	public static final String MSG = "msg";
 	// ros2 service command option
 	public static final String SRV = "srv";
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/Ros2ProcessBuilder.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/Ros2ProcessBuilder.java
index 3eb9971..650a938 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/Ros2ProcessBuilder.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/Ros2ProcessBuilder.java
@@ -4,19 +4,24 @@
 import java.util.List;
 import java.util.Map;
 
-import org.eclipse.papyrus.robotics.ros2.preferences.Ros2PreferenceUtils;
-
 public class Ros2ProcessBuilder {
 
+	private static final String ROS2 = "ros2"; //$NON-NLS-1$
+	
 	ProcessBuilder pb;
 
-	public Ros2ProcessBuilder(String... commands) {
+	public Ros2ProcessBuilder(String... cmdParams) {
 		pb = new ProcessBuilder();
-		// ROS2 path
-		String ros2Path = String.format("%s/bin/ros2", Ros2PreferenceUtils.getRosDistroPath());
-		pb.command().add(ros2Path);
-		for(String command : commands) {
-			pb.command().add(command);
+		String ros2 = EnvironmentUtils.getFromPath(ROS2);
+		if (ros2 == null) {
+			// don't throw an exception, otherwise the tests (running on a machine
+			// without ROS2 installed) are failing. Fall back to ros2, even if the
+			// command cannot be executed in that case.
+			ros2 = ROS2;
+		}
+		pb.command().add(ros2);
+		for(String cmdParam : cmdParams) {
+			pb.command().add(cmdParam);
 		}
 		Map<String, String> localEnv = EnvironmentUtils.getenv();
 		Map<String, String> pbEnv = pb.environment();