remote-executor

Details

.gitignore 34(+34 -0)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4a482b8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,34 @@
+# ignore eclipse project files
+.project
+.classpath
+
+# ignore Intellij Idea project files
+.idea
+*.iml
+
+# Netbeans
+/nbproject/
+/nbactions.xml
+
+# Netbeans deploy
+/build/
+
+# Maven deploy
+/target/
+
+# Ant deploy
+/dist/
+
+# Class files
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*

pom.xml 52(+52 -0)

diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..59355a0
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>br.ufrgs.inf.prosoft.remoteexecutor</groupId>
+    <artifactId>RemoteExecutor</artifactId>
+    <version>1.0</version>
+    <packaging>jar</packaging>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+    </properties>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>
+                                ${project.build.directory}/lib
+                            </outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>3.1.0</version>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <addClasspath>true</addClasspath>
+                            <classpathPrefix>lib</classpathPrefix>
+                            <mainClass>br.ufrgs.inf.prosoft.remoteexecutor.Main</mainClass>
+                        </manifest>
+                        <manifestEntries>
+                            <Class-Path>lib/</Class-Path>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/src/main/java/br/ufrgs/inf/prosoft/remoteexecutor/Client.java b/src/main/java/br/ufrgs/inf/prosoft/remoteexecutor/Client.java
new file mode 100644
index 0000000..60add23
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/remoteexecutor/Client.java
@@ -0,0 +1,69 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.remoteexecutor;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author romulo
+ */
+public class Client {
+
+    private static final Logger LOGGER = Logger.getLogger(Client.class.getName());
+
+    public static int send(String message, String host, int port) {
+        Socket socket = null;
+        OutputStream outputStream = null;
+        InputStream inputStream = null;
+        int signal = 0;
+        try {
+            socket = new Socket(host, port);
+            outputStream = socket.getOutputStream();
+            LOGGER.log(Level.INFO, "< {0}", message);
+            message += "\n";
+            outputStream.write(message.getBytes());
+            inputStream = socket.getInputStream();
+            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
+            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+            String response = bufferedReader.readLine();
+            LOGGER.log(Level.INFO, "> {0}", response);
+        } catch (IOException ex) {
+            LOGGER.log(Level.SEVERE, "could not connect to {0}:" + port, host);
+            signal = 1;
+        } catch (Exception ex) {
+            LOGGER.log(Level.SEVERE, "exception: {0}", ex);
+            signal = 2;
+        } finally {
+            if (outputStream != null) {
+                try {
+                    outputStream.close();
+                } catch (IOException ex) {
+                }
+            }
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException ex) {
+                }
+            }
+            if (socket != null) {
+                try {
+                    socket.close();
+                } catch (IOException ex) {
+                }
+            }
+        }
+        return signal;
+    }
+}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/remoteexecutor/Main.java b/src/main/java/br/ufrgs/inf/prosoft/remoteexecutor/Main.java
new file mode 100644
index 0000000..5edaaf3
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/remoteexecutor/Main.java
@@ -0,0 +1,87 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.remoteexecutor;
+
+import java.io.File;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ *
+ * @author romulo
+ */
+public class Main {
+
+    private static final Logger LOGGER = Logger.getLogger(Main.class.getName());
+
+    public static void main(String[] args) {
+        System.setProperty("java.util.logging.SimpleFormatter.format", "[%1$tF %1$tT+%1$tL] [%4$-7s] [RemoteExecutor] %5$s %n");
+
+        if (args.length < 1) {
+            System.err.println("[--listen=<port> | --home=<homePath>]");
+            System.err.println("--send=<message> [--host=<host>] [--port=<port>]");
+            System.exit(1);
+        }
+
+        Map<String, String> arguments = Stream.of(args).map(arg -> {
+            arg = arg.replaceFirst("--", "");
+            int indexOf = arg.indexOf("=");
+            if (indexOf == -1) {
+                return new String[]{arg, ""};
+            }
+            return new String[]{arg.substring(0, indexOf), arg.substring(indexOf + 1)};
+        }).collect(Collectors.toMap(array -> {
+            return array[0];
+        }, array -> {
+            return array[1];
+        }));
+
+        String listen = arguments.get("listen");
+        String homePath = arguments.get("home");
+        String send = arguments.get("send");
+        if (listen == null && homePath == null && send == null) {
+            System.err.println("[--listen=<port> | --home=<homePath>]");
+            System.err.println("--send=<message> [--host=<host>] [--port=<port>]");
+            System.exit(1);
+        }
+
+        int port = 5000;
+        if (send != null) {
+            String host = arguments.get("host");
+            String portStr = arguments.get("port");
+            if (host == null) {
+                host = "localhost";
+                LOGGER.log(Level.INFO, "<host> not defined. Using {0}", host);
+            }
+            if (portStr == null) {
+                LOGGER.log(Level.INFO, "<port> not defined. Using " + port);
+            } else {
+                try {
+                    port = Integer.valueOf(portStr);
+                } catch (NumberFormatException ex) {
+                    LOGGER.log(Level.INFO, "<port> incorrectly defined. Using default: " + port);
+                }
+            }
+            int signal = Client.send(send, host, port);
+            System.exit(signal);
+        }
+
+        if (homePath == null) {
+            homePath = ".";
+            LOGGER.log(Level.INFO, "<home> not defined. Using default: {0}", homePath);
+        }
+
+        if (listen == null) {
+            LOGGER.log(Level.INFO, "<port> not defined. Using " + port);
+        }
+
+        File home = new File(homePath);
+        Server.listen(home, port);
+    }
+}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/remoteexecutor/Server.java b/src/main/java/br/ufrgs/inf/prosoft/remoteexecutor/Server.java
new file mode 100644
index 0000000..f93b312
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/remoteexecutor/Server.java
@@ -0,0 +1,114 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.remoteexecutor;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author romulo
+ */
+public class Server {
+
+    private static final Logger LOGGER = Logger.getLogger(Server.class.getName());
+
+    public static void listen(File home, int port) {
+        ServerSocket serverSocket = null;
+        try {
+            serverSocket = new ServerSocket(port);
+            LOGGER.log(Level.INFO, "start listening on port " + port);
+            boolean exit = false;
+            while (!exit) {
+                Socket socket = null;
+                InputStream inputStream = null;
+                OutputStream outputStream = null;
+                try {
+                    socket = serverSocket.accept();
+                    inputStream = socket.getInputStream();
+                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
+                    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+                    String message = bufferedReader.readLine();
+                    if (message == null) {
+                        message = "";
+                    }
+                    LOGGER.log(Level.INFO, "> {0}", message);
+                    if (message.startsWith("caching-approaches-comparison ")) {
+                        String command = message.replaceFirst("caching-approaches-comparison ", "");
+                        if (command.equals("exit")) {
+                            exit = true;
+                        } else {
+                            try {
+                                ProcessBuilder processBuilder = new ProcessBuilder();
+                                processBuilder.directory(home);
+                                String[] commandArray = command.split(" ");
+                                List<String> commandList = Arrays.asList(commandArray);
+                                if (commandList.get(0).contains("=")) {
+                                    String[] map = commandList.get(0).split("=");
+                                    processBuilder.environment().put(map[0], map[1]);
+                                    commandList = commandList.subList(1, commandList.size());
+                                }
+                                processBuilder.command(commandList);
+                                processBuilder.inheritIO();
+                                processBuilder.start();
+                            } catch (Exception ex) {
+                                LOGGER.log(Level.WARNING, ex.getMessage());
+                                message = "command failed";
+                            }
+                        }
+                    }
+                    message = "[RemoteExecutor] " + message;
+                    LOGGER.log(Level.INFO, "< {0}", message);
+                    message += "\n";
+                    outputStream = socket.getOutputStream();
+                    outputStream.write(message.getBytes());
+                } catch (IOException ex) {
+                    LOGGER.log(Level.WARNING, "connection closed before echo is sent");
+                } catch (Exception ex) {
+                    LOGGER.log(Level.WARNING, "exception: {0}", ex);
+                } finally {
+                    if (inputStream != null) {
+                        try {
+                            inputStream.close();
+                        } catch (IOException ex) {
+                        }
+                    }
+                    if (outputStream != null) {
+                        try {
+                            outputStream.close();
+                        } catch (IOException ex) {
+                        }
+                    }
+                    if (socket != null) {
+                        try {
+                            socket.close();
+                        } catch (IOException ex) {
+                        }
+                    }
+                }
+            }
+        } catch (IOException ex) {
+            LOGGER.log(Level.SEVERE, "port " + port + " is busy");
+        } finally {
+            if (serverSocket != null) {
+                try {
+                    serverSocket.close();
+                } catch (IOException ex) {
+                }
+            }
+        }
+    }
+}