From 3e403cb0dd65f07a0d69b1b45403eb361a95681a Mon Sep 17 00:00:00 2001
From: Ernesto Corbellini <ecorbellini@creativa77.com.ar>
Date: Fri, 25 Sep 2015 17:50:22 -0300
Subject: [PATCH] Added a new node class to wrap the loading and execution of a
 native code ROS node.

---
 .../java/org/ros/node/NativeNodeMain.java     | 103 ++++++++++++++++++
 1 file changed, 103 insertions(+)
 create mode 100644 rosjava/src/main/java/org/ros/node/NativeNodeMain.java

diff --git a/rosjava/src/main/java/org/ros/node/NativeNodeMain.java b/rosjava/src/main/java/org/ros/node/NativeNodeMain.java
new file mode 100644
index 00000000..e483fa06
--- /dev/null
+++ b/rosjava/src/main/java/org/ros/node/NativeNodeMain.java
@@ -0,0 +1,103 @@
+package org.ros.node;
+
+import org.ros.node.AbstractNodeMain;
+import org.ros.node.ConnectedNode;
+import org.ros.node.Node;
+import org.ros.namespace.GraphName;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A java wrapper to load and run a native-code ROS node.
+ * 
+ * Note: there are no actual native methods declared in this class. We only define an interface. The native methods should be declared in the child class.
+ * 
+ * @author ecorbellini@creativa77.com.ar (Ernesto Corbellini)
+ */
+public abstract class NativeNodeMain extends AbstractNodeMain {
+  
+  private Log log = LogFactory.getLog(NativeNodeMain.class);
+  private String libName;
+  private String masterUri = null;
+  private String hostName = null;
+  private String nodeName = null;
+  private String[] remappingArguments;
+  private boolean shuttingDown = false;
+  
+  /**
+   *  @param libName
+   *    The name of the library to load.
+   * 
+   *  @param remappings
+   *    A string array with ROS argument remapping pairs in each element.
+   **/
+  public NativeNodeMain(String libName, String[] remappings) {
+    this.libName = libName;
+    
+    // if no remapping is needed, create an empty array
+    if (remappings == null) {
+      remappingArguments = new String[0];
+    }
+    
+    log.info("Trying to load native library '" + libName + "'...");
+    try
+    {
+      System.loadLibrary(libName);
+    }
+    catch (SecurityException e)
+    {
+      log.info("Error loading library! SecurityException");
+    }
+    catch (UnsatisfiedLinkError e)
+    {
+      log.info("Error loading library! UnsatisfiedLinkError");
+    }
+    catch (NullPointerException e)
+    {
+      log.info("Error loading library! NullPointerException");
+    }
+  }
+
+  /**
+   *  @param libName
+   *    The name of the library to load.
+   **/
+  public NativeNodeMain(String libName) {
+    this(libName, null);
+  }
+
+  // These methods define the execution model interface for this node.
+  protected abstract void execute(String rosMasterUri, String rosHostName, String rosNodeName, String[] remappingArguments);
+  protected abstract void shutdown();
+  
+  @Override
+  public void onStart(final ConnectedNode connectedNode) {
+    // retain important ROS info
+    masterUri = connectedNode.getMasterUri().toString();
+    hostName = connectedNode.getUri().getHost();
+    nodeName = this.libName;
+
+    // create a new thread to execute the native code.
+    new Thread() {
+      @Override
+      public void run() {
+        execute(masterUri, hostName, nodeName, remappingArguments);
+        
+        // node execution has finished so we propagate the shutdown sequence only if we aren't already shutting down for other reasons
+        if(!shuttingDown) {
+          connectedNode.shutdown();
+        }
+      }
+    }.start();
+  }
+  
+  @Override
+  public void onShutdown(Node node) {
+    shuttingDown = true;
+    shutdown();
+  }
+}
-- 
GitLab