Browse Source

added abstract command executor; dynamic load and execution of executors

develop
Robin Thoni 8 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
-package com.uqac.rthoni.com.java_rmi.client;
1
+package com.uqac.rthoni.java_rmi.client;
2
 
2
 
3
 import com.uqac.rthoni.java_rmi.common.Command;
3
 import com.uqac.rthoni.java_rmi.common.Command;
4
 
4
 
11
  */
11
  */
12
 public class ClientApplication {
12
 public class ClientApplication {
13
 
13
 
14
-    public static Vector<Command> readInputFile(String file)
14
+    public Vector<Command> readInputFile(String file)
15
     {
15
     {
16
         FileInputStream fileInputStream = null;
16
         FileInputStream fileInputStream = null;
17
         try {
17
         try {
41
         return lines;
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
         System.out.format("Reading input file %s...\n", inputFile);
46
         System.out.format("Reading input file %s...\n", inputFile);
47
         Vector<Command> commands = readInputFile(inputFile);
47
         Vector<Command> commands = readInputFile(inputFile);
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
         System.out.format("Running command %s...\n", command.getCommandName());
66
         System.out.format("Running command %s...\n", command.getCommandName());
67
         System.out.format("Connecting to %s:%d...\n", host, port);
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

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
-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
 import com.uqac.rthoni.java_rmi.common.Command;
4
 import com.uqac.rthoni.java_rmi.common.Command;
4
 
5
 
5
 import java.io.BufferedReader;
6
 import java.io.BufferedReader;
8
 import java.net.InetAddress;
9
 import java.net.InetAddress;
9
 import java.net.ServerSocket;
10
 import java.net.ServerSocket;
10
 import java.net.Socket;
11
 import java.net.Socket;
12
+import java.util.Vector;
11
 
13
 
12
 /**
14
 /**
13
  * Created by robin on 9/15/16.
15
  * Created by robin on 9/15/16.
14
  */
16
  */
15
 public class ServerApplication {
17
 public class ServerApplication {
16
 
18
 
19
+    private Vector<AbstractCommandExecutor> _executors = null;
20
+
17
     public static String ipToString(InetAddress ip) {
21
     public static String ipToString(InetAddress ip) {
18
         String ipString = ip.toString();
22
         String ipString = ip.toString();
19
         if (!ipString.isEmpty() && ipString.startsWith("/")) {
23
         if (!ipString.isEmpty() && ipString.startsWith("/")) {
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
         String host = "0.0.0.0";
48
         String host = "0.0.0.0";
38
         InetAddress ip = null;
49
         InetAddress ip = null;
39
         try {
50
         try {
43
         }
54
         }
44
         if (ip == null) {
55
         if (ip == null) {
45
             System.err.format("Failed to resolve '%s'\n", host);
56
             System.err.format("Failed to resolve '%s'\n", host);
46
-            System.exit(1);
57
+            System.exit(2);
47
         }
58
         }
48
         String ipString = ipToString(ip);
59
         String ipString = ipToString(ip);
49
 
60
 
53
             runServer(serverSocket);
64
             runServer(serverSocket);
54
         } catch (IOException e) {
65
         } catch (IOException e) {
55
             System.err.format("Failed to listen on %s:%d: %s\n", ipString, port, e.getMessage());
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
             Socket client = null;
88
             Socket client = null;
65
             try {
89
             try {
66
                 client = serverSocket.accept();
90
                 client = serverSocket.accept();
85
         }
109
         }
86
     }
110
     }
87
 
111
 
88
-    private static void handleClient(Socket client)
112
+    private void handleClient(Socket client)
89
     {
113
     {
90
         String str;
114
         String str;
91
         try {
115
         try {
101
         }
125
         }
102
         else {
126
         else {
103
             System.out.format("Received command: %s\n", command.getCommandName());
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
             try {
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

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

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
 package com.uqac.rthoni.java_rmi;
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
 import java.io.PrintStream;
6
 import java.io.PrintStream;
7
 
7
 
66
             String classDir = args[3];
66
             String classDir = args[3];
67
             String logFile = args[4];
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
         else if (mode.equals("client")) {
72
         else if (mode.equals("client")) {
72
             String host = args[1];
73
             String host = args[1];
74
             String inputFile = args[3];
75
             String inputFile = args[3];
75
             String outputFile = args[4];
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
         else {
81
         else {
80
             usage(name, true);
82
             usage(name, true);

Loading…
Cancel
Save