Browse Source

added abstract command executor; dynamic load and execution of executors

develop
Robin Thoni 7 years ago
parent
commit
f2ca3e1bcc

client/src/main/java/com/uqac/rthoni/com/java_rmi/client/ClientApplication.java → client/src/main/java/com/uqac/rthoni/java_rmi/client/ClientApplication.java View File

@@ -1,4 +1,4 @@
1
-package com.uqac.rthoni.com.java_rmi.client;
1
+package com.uqac.rthoni.java_rmi.client;
2 2
 
3 3
 import com.uqac.rthoni.java_rmi.common.Command;
4 4
 
@@ -11,7 +11,7 @@ import java.util.Vector;
11 11
  */
12 12
 public class ClientApplication {
13 13
 
14
-    public static Vector<Command> readInputFile(String file)
14
+    public Vector<Command> readInputFile(String file)
15 15
     {
16 16
         FileInputStream fileInputStream = null;
17 17
         try {
@@ -41,7 +41,7 @@ public class ClientApplication {
41 41
         return lines;
42 42
     }
43 43
 
44
-    public static void run(String host, int port, String inputFile, String outputFile)
44
+    public void run(String host, int port, String inputFile, String outputFile)
45 45
     {
46 46
         System.out.format("Reading input file %s...\n", inputFile);
47 47
         Vector<Command> commands = readInputFile(inputFile);
@@ -61,7 +61,7 @@ public class ClientApplication {
61 61
         }
62 62
     }
63 63
 
64
-    private static void runCommand(Command command, String host, int port, OutputStream outputStream)
64
+    private void runCommand(Command command, String host, int port, OutputStream outputStream)
65 65
     {
66 66
         System.out.format("Running command %s...\n", command.getCommandName());
67 67
         System.out.format("Connecting to %s:%d...\n", host, port);

+ 76
- 0
common/src/main/java/com/uqac/rthoni/java_rmi/common/ReflectionUtil.java View File

@@ -0,0 +1,76 @@
1
+package com.uqac.rthoni.java_rmi.common;
2
+
3
+import java.io.File;
4
+import java.io.IOException;
5
+import java.io.UnsupportedEncodingException;
6
+import java.net.JarURLConnection;
7
+import java.net.URL;
8
+import java.net.URLDecoder;
9
+import java.util.*;
10
+import java.util.jar.JarEntry;
11
+import java.util.jar.JarFile;
12
+import java.util.stream.Collectors;
13
+
14
+/**
15
+ * Created by robin on 9/16/16.
16
+ */
17
+public class ReflectionUtil {
18
+
19
+    public static Vector<Class> getClassesForPackage(String pckgname)
20
+            throws ClassNotFoundException {
21
+
22
+        Vector<Class> classes = new Vector<>();
23
+        ArrayList<File> directories = new ArrayList<>();
24
+        try {
25
+            ClassLoader cld = Thread.currentThread().getContextClassLoader();
26
+
27
+            Enumeration<URL> resources = cld.getResources(pckgname.replace('.', '/'));
28
+            while (resources.hasMoreElements()) {
29
+                URL res = resources.nextElement();
30
+                if (res.getProtocol().equalsIgnoreCase("jar")){
31
+                    JarURLConnection conn = (JarURLConnection) res.openConnection();
32
+                    JarFile jar = conn.getJarFile();
33
+                    for (JarEntry e: Collections.list(jar.entries())){
34
+
35
+                        if(e.getName().startsWith(pckgname.replace('.', '/'))
36
+                                && e.getName().endsWith(".class") && !e.getName().contains("$")){
37
+                            String className = e.getName().replace("/",".").substring(0,e.getName().length() - 6);
38
+                            classes.add(Class.forName(className));
39
+                        }
40
+                    }
41
+                }else
42
+                    directories.add(new File(URLDecoder.decode(res.getPath(), "UTF-8")));
43
+            }
44
+        } catch (Exception e) {
45
+            throw new ClassNotFoundException(String.format("Failed to get jar info: %s", e.getMessage()));
46
+        }
47
+
48
+        // For every directory identified capture all the .class files
49
+        for (File directory : directories) {
50
+            if (directory.exists()) {
51
+                // Get the list of the files contained in the package
52
+                String[] files = directory.list();
53
+                for (String file : files) {
54
+                    // we are only interested in .class files
55
+                    if (file.endsWith(".class")) {
56
+                        // removes the .class extension
57
+                        classes.add(Class.forName(pckgname + '.' + file.substring(0, file.length() - 6)));
58
+                    }
59
+                }
60
+            } else {
61
+                throw new ClassNotFoundException(String.format("Failed to get class file for %s", directory.getName()));
62
+            }
63
+        }
64
+        return classes;
65
+    }
66
+
67
+    public static Vector<Class> getClassesOfSuperClass(String thePackage, Class superClass)
68
+            throws ClassNotFoundException {
69
+        Vector<Class> classList = new Vector<>();
70
+        classList.addAll(getClassesForPackage(thePackage).stream()
71
+                .filter(discovered -> Collections.singletonList(discovered.getSuperclass())
72
+                        .contains(superClass)).collect(Collectors.toList()));
73
+
74
+        return classList;
75
+    }
76
+}

server/src/main/java/com/uqac/rthoni/com/java_rmi/server/ServerApplication.java → server/src/main/java/com/uqac/rthoni/java_rmi/server/ServerApplication.java View File

@@ -1,5 +1,6 @@
1
-package com.uqac.rthoni.com.java_rmi.server;
1
+package com.uqac.rthoni.java_rmi.server;
2 2
 
3
+import com.uqac.rthoni.java_rmi.server.executors.AbstractCommandExecutor;
3 4
 import com.uqac.rthoni.java_rmi.common.Command;
4 5
 
5 6
 import java.io.BufferedReader;
@@ -8,12 +9,15 @@ import java.io.InputStreamReader;
8 9
 import java.net.InetAddress;
9 10
 import java.net.ServerSocket;
10 11
 import java.net.Socket;
12
+import java.util.Vector;
11 13
 
12 14
 /**
13 15
  * Created by robin on 9/15/16.
14 16
  */
15 17
 public class ServerApplication {
16 18
 
19
+    private Vector<AbstractCommandExecutor> _executors = null;
20
+
17 21
     public static String ipToString(InetAddress ip) {
18 22
         String ipString = ip.toString();
19 23
         if (!ipString.isEmpty() && ipString.startsWith("/")) {
@@ -32,8 +36,15 @@ public class ServerApplication {
32 36
         }
33 37
     }
34 38
 
35
-    public static void run(int port, String sourceDir, String classDir, String logFile)
39
+    public void run(int port, String sourceDir, String classDir, String logFile)
36 40
     {
41
+        try {
42
+            loadExecutors();
43
+        } catch (ClassNotFoundException e) {
44
+            System.err.format("Failed to load executors: %s\n", e.getMessage());
45
+            System.exit(1);
46
+        }
47
+
37 48
         String host = "0.0.0.0";
38 49
         InetAddress ip = null;
39 50
         try {
@@ -43,7 +54,7 @@ public class ServerApplication {
43 54
         }
44 55
         if (ip == null) {
45 56
             System.err.format("Failed to resolve '%s'\n", host);
46
-            System.exit(1);
57
+            System.exit(2);
47 58
         }
48 59
         String ipString = ipToString(ip);
49 60
 
@@ -53,14 +64,27 @@ public class ServerApplication {
53 64
             runServer(serverSocket);
54 65
         } catch (IOException e) {
55 66
             System.err.format("Failed to listen on %s:%d: %s\n", ipString, port, e.getMessage());
56
-            System.exit(2);
67
+            System.exit(3);
57 68
         }
58 69
     }
59 70
 
60
-    public static void runServer(ServerSocket serverSocket)
71
+    private void loadExecutors() throws ClassNotFoundException
61 72
     {
62
-        boolean stop = false;
63
-        while (!stop) {
73
+        _executors = new Vector<>();
74
+        Vector<Class> classes = AbstractCommandExecutor.getAllExecutors();
75
+        for (Class c : classes) {
76
+            try {
77
+                AbstractCommandExecutor executor = (AbstractCommandExecutor)c.newInstance();
78
+                _executors.add(executor);
79
+            } catch (Exception e) {
80
+                System.err.format("Failed to load executor '%s': %s\n", c.getName(), e.getMessage());
81
+            }
82
+        }
83
+    }
84
+
85
+    private void runServer(ServerSocket serverSocket)
86
+    {
87
+        while (true) {
64 88
             Socket client = null;
65 89
             try {
66 90
                 client = serverSocket.accept();
@@ -85,7 +109,7 @@ public class ServerApplication {
85 109
         }
86 110
     }
87 111
 
88
-    private static void handleClient(Socket client)
112
+    private void handleClient(Socket client)
89 113
     {
90 114
         String str;
91 115
         try {
@@ -101,11 +125,42 @@ public class ServerApplication {
101 125
         }
102 126
         else {
103 127
             System.out.format("Received command: %s\n", command.getCommandName());
128
+
129
+            handleCommand(command, client);
130
+        }
131
+    }
132
+
133
+    private AbstractCommandExecutor getExecutor(Command command)
134
+    {
135
+        for (AbstractCommandExecutor executor : _executors) {
136
+            if (executor.getCommandName().equals(command.getCommandName())) {
137
+                return executor;
138
+            }
139
+        }
140
+        return null;
141
+    }
142
+
143
+    private void handleCommand(Command command, Socket client)
144
+    {
145
+        String data;
146
+        AbstractCommandExecutor executor = getExecutor(command);
147
+        if (executor == null) {
148
+            data = String.format("Unknown command '%s'", command.getCommandName());
149
+            System.err.println(data);
150
+        }
151
+        else {
104 152
             try {
105
-                client.getOutputStream().write("test\n".getBytes());
106
-            } catch (IOException e) {
107
-                e.printStackTrace();
153
+                data = executor.run(command);
154
+            } catch (Exception e) {
155
+                data = String.format("Error when handling command: %s", e.getMessage());
156
+                System.err.println(data);
108 157
             }
109 158
         }
159
+
160
+        try {
161
+            client.getOutputStream().write(String.format("%s\n", data).getBytes());
162
+        } catch (IOException e) {
163
+            e.printStackTrace();
164
+        }
110 165
     }
111 166
 }

+ 21
- 0
server/src/main/java/com/uqac/rthoni/java_rmi/server/executors/AbstractCommandExecutor.java View File

@@ -0,0 +1,21 @@
1
+package com.uqac.rthoni.java_rmi.server.executors;
2
+
3
+import com.uqac.rthoni.java_rmi.common.Command;
4
+import com.uqac.rthoni.java_rmi.common.ReflectionUtil;
5
+
6
+import java.util.Vector;
7
+
8
+/**
9
+ * Created by robin on 9/16/16.
10
+ */
11
+public abstract class AbstractCommandExecutor {
12
+
13
+    public static Vector<Class> getAllExecutors() throws ClassNotFoundException
14
+    {
15
+        return ReflectionUtil.getClassesOfSuperClass(AbstractCommandExecutor.class.getPackage().getName(), AbstractCommandExecutor.class);
16
+    }
17
+
18
+    public abstract String getCommandName();
19
+
20
+    public abstract String run(Command command) throws Exception;
21
+}

+ 18
- 0
server/src/main/java/com/uqac/rthoni/java_rmi/server/executors/TestExecutor.java View File

@@ -0,0 +1,18 @@
1
+package com.uqac.rthoni.java_rmi.server.executors;
2
+
3
+import com.uqac.rthoni.java_rmi.common.Command;
4
+
5
+/**
6
+ * Created by robin on 9/16/16.
7
+ */
8
+public class TestExecutor extends AbstractCommandExecutor {
9
+    @Override
10
+    public String getCommandName() {
11
+        return "test";
12
+    }
13
+
14
+    @Override
15
+    public String run(Command command) throws Exception {
16
+        return "Test. succeeded";
17
+    }
18
+}

+ 6
- 4
src/main/java/com/uqac/rthoni/java_rmi/Main.java View File

@@ -1,7 +1,7 @@
1 1
 package com.uqac.rthoni.java_rmi;
2 2
 
3
-import com.uqac.rthoni.com.java_rmi.client.ClientApplication;
4
-import com.uqac.rthoni.com.java_rmi.server.ServerApplication;
3
+import com.uqac.rthoni.java_rmi.client.ClientApplication;
4
+import com.uqac.rthoni.java_rmi.server.ServerApplication;
5 5
 
6 6
 import java.io.PrintStream;
7 7
 
@@ -66,7 +66,8 @@ public class Main {
66 66
             String classDir = args[3];
67 67
             String logFile = args[4];
68 68
 
69
-            ServerApplication.run(port, sourceDir, classDir, logFile);
69
+            ServerApplication app = new ServerApplication();
70
+            app.run(port, sourceDir, classDir, logFile);
70 71
         }
71 72
         else if (mode.equals("client")) {
72 73
             String host = args[1];
@@ -74,7 +75,8 @@ public class Main {
74 75
             String inputFile = args[3];
75 76
             String outputFile = args[4];
76 77
 
77
-            ClientApplication.run(host, port, inputFile, outputFile);
78
+            ClientApplication app = new ClientApplication();
79
+            app.run(host, port, inputFile, outputFile);
78 80
         }
79 81
         else {
80 82
             usage(name, true);

Loading…
Cancel
Save