From 3d04b20dca9b5502f506d98a07de8c642ee52ccb Mon Sep 17 00:00:00 2001 From: GideonLeGrange Date: Mon, 23 Jun 2014 11:19:15 +0200 Subject: [PATCH 1/2] Created version 2.0.0 branch to fix a few non-backwards compatibile problems. - Added error() and completed() to ResultListener - Removed ResponseListener - Refactored internals and examples to account for these changes. --- src/main/java/examples/Config.java | 2 +- src/main/java/examples/Example4.java | 14 ++++- src/main/java/examples/Example5.java | 4 +- .../legrange/mikrotik/ResponseListener.java | 17 ------ .../me/legrange/mikrotik/ResultListener.java | 7 +++ .../mikrotik/impl/ApiConnectionImpl.java | 58 +++++++++---------- 6 files changed, 49 insertions(+), 53 deletions(-) delete mode 100644 src/main/java/me/legrange/mikrotik/ResponseListener.java diff --git a/src/main/java/examples/Config.java b/src/main/java/examples/Config.java index 67dcab9..e76b404 100644 --- a/src/main/java/examples/Config.java +++ b/src/main/java/examples/Config.java @@ -7,7 +7,7 @@ package examples; public class Config { - public static final String HOST = "10.0.1.134"; + public static final String HOST = "10.0.1.1"; public static final String USERNAME = "admin"; public static final String PASSWORD = ""; diff --git a/src/main/java/examples/Example4.java b/src/main/java/examples/Example4.java index 5844f4d..cdda4b1 100644 --- a/src/main/java/examples/Example4.java +++ b/src/main/java/examples/Example4.java @@ -19,14 +19,24 @@ public class Example4 extends Example { } private void test() throws MikrotikApiException, InterruptedException { - String id = con.execute("/interface/wireless/monitor .id=wlan1", new ResultListener() { + String id = con.execute("/interface/wireless/monitor .id=wlan1 .proplist=signal-strength", new ResultListener() { private int prev = 0; public void receive(Map result) { - int val = Integer.parseInt(result.get("signal-strength")); + System.out.println(result); +/* int val = Integer.parseInt(result.get("signal-strength")); String sym = (val == prev) ? " " : ((val < prev) ? "-" : "+"); System.out.printf("%d %s\n", val, sym); prev = val; + */ } + + @Override + public void error(MikrotikApiException ex) { + throw new RuntimeException(ex.getMessage(), ex); + } + + @Override + public void completed() { } diff --git a/src/main/java/examples/Example5.java b/src/main/java/examples/Example5.java index 8bc4903..32dd190 100644 --- a/src/main/java/examples/Example5.java +++ b/src/main/java/examples/Example5.java @@ -2,7 +2,7 @@ package examples; import java.util.Map; import me.legrange.mikrotik.MikrotikApiException; -import me.legrange.mikrotik.ResponseListener; +import me.legrange.mikrotik.ResultListener; /** * Example 5: Asynchronous results, with error and completion. Run a command and receive results, errors and completion notification for it asynchronously with a ResponseListener @@ -20,7 +20,7 @@ public class Example5 extends Example { private void test() throws MikrotikApiException, InterruptedException { boolean completed = false; - String id = con.execute("/interface/wireless/monitor .id=wlan1", new ResponseListener() { + String id = con.execute("/interface/wireless/monitor .id=wlan1", new ResultListener() { private int prev = 0; public void receive(Map result) { diff --git a/src/main/java/me/legrange/mikrotik/ResponseListener.java b/src/main/java/me/legrange/mikrotik/ResponseListener.java deleted file mode 100644 index 1ebe1b3..0000000 --- a/src/main/java/me/legrange/mikrotik/ResponseListener.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.legrange.mikrotik; - -/** - * A listener that receives life cycle command events from the Mikrotik API, - * and not just results. - * @author GideonLeGrange - */ -public interface ResponseListener extends ResultListener { - - /** called if the command associated with this listener experiences an error */ - void error(MikrotikApiException ex); - - /** called when the command associated with this listener is done */ - void completed(); - - -} diff --git a/src/main/java/me/legrange/mikrotik/ResultListener.java b/src/main/java/me/legrange/mikrotik/ResultListener.java index 716a9f8..b9416fc 100644 --- a/src/main/java/me/legrange/mikrotik/ResultListener.java +++ b/src/main/java/me/legrange/mikrotik/ResultListener.java @@ -9,5 +9,12 @@ import java.util.Map; public interface ResultListener { void receive(Map result); + + /** called if the command associated with this listener experiences an error + * @param ex Exception encountered */ + void error(MikrotikApiException ex); + /** called when the command associated with this listener is done */ + void completed(); + } diff --git a/src/main/java/me/legrange/mikrotik/impl/ApiConnectionImpl.java b/src/main/java/me/legrange/mikrotik/impl/ApiConnectionImpl.java index 6b24da6..88450dc 100644 --- a/src/main/java/me/legrange/mikrotik/impl/ApiConnectionImpl.java +++ b/src/main/java/me/legrange/mikrotik/impl/ApiConnectionImpl.java @@ -33,7 +33,8 @@ public final class ApiConnectionImpl extends ApiConnection { * @param port The TCP port to use. * @param secure Is TLS required * @return The ApiConnection - * @throws me.legrange.mikrotik.ApiConnectionException Thrown if there is a problem connecting + * @throws me.legrange.mikrotik.ApiConnectionException Thrown if there is a + * problem connecting */ public static ApiConnection connect(String host, int port, boolean secure) throws ApiConnectionException { ApiConnectionImpl con = new ApiConnectionImpl(); @@ -53,7 +54,9 @@ public final class ApiConnectionImpl extends ApiConnection { /** * Disconnect from the remote API - * @throws me.legrange.mikrotik.ApiConnectionException Thrown if there is a problem disconnecting + * + * @throws me.legrange.mikrotik.ApiConnectionException Thrown if there is a + * problem disconnecting */ @Override public void disconnect() throws ApiConnectionException { @@ -284,22 +287,15 @@ public final class ApiConnectionImpl extends ApiConnection { if (l != null) { if (res instanceof Result) { l.receive((Result) res); - } else { - if (res instanceof Done) { - listeners.remove(res.getTag()); - } - if (l instanceof ResponseListener) { - ResponseListener rl = (ResponseListener) l; - if (res instanceof Done) { - if (rl instanceof SyncListener) { - ((SyncListener) rl).completed((Done) res); - } else { - rl.completed(); - } - } else if (res instanceof Error) { - rl.error(new ApiCommandException((Error) res)); - } + } else if (res instanceof Done) { + if (l instanceof SyncListener) { + ((SyncListener) l).completed((Done) res); + } else { + l.completed(); } + listeners.remove(res.getTag()); + } else if (res instanceof Error) { + l.error(new ApiCommandException((Error) res)); } } } @@ -322,16 +318,17 @@ public final class ApiConnectionImpl extends ApiConnection { if (line == null) { nextLine(); } - if (line.equals("!re")) { - return unpackRe(); - } else if (line.equals("!done")) { - return unpackDone(); - } else if (line.equals("!trap")) { - return unpackError(); - } else if (line.equals("!halt")) { - return unpackError(); - } else { - throw new ApiDataException(String.format("Unexpected line '%s'", line)); + switch (line) { + case "!re": + return unpackRe(); + case "!done": + return unpackDone(); + case "!trap": + return unpackError(); + case "!halt": + return unpackError(); + default: + throw new ApiDataException(String.format("Unexpected line '%s'", line)); } } @@ -346,8 +343,7 @@ public final class ApiConnectionImpl extends ApiConnection { if (parts.length == 3) { if (!parts[2].endsWith("\r")) { res.put(parts[1], parts[2]); - } - else { + } else { res.put(parts[1], unpackMultiLine(parts[2])); } } else { @@ -379,7 +375,7 @@ public final class ApiConnectionImpl extends ApiConnection { } while (line.endsWith("\r")); return buf.toString(); } - + private Done unpackDone() throws MikrotikApiException { Done done = new Done(null); if (hasNextLine()) { @@ -451,7 +447,7 @@ public final class ApiConnectionImpl extends ApiConnection { private String line; } - private class SyncListener implements ResponseListener { + private class SyncListener implements ResultListener { public synchronized void error(MikrotikApiException ex) { this.err = ex; From 9e0f38149d14cde26a3c5e0439ccdb2944a6b180 Mon Sep 17 00:00:00 2001 From: GideonLeGrange Date: Mon, 23 Jun 2014 11:26:15 +0200 Subject: [PATCH 2/2] Modified README to explain version 2.0.0 --- README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index efbfdd7..a6707b4 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,10 @@ The current stable version is 1.1.6, which managed to get into Maven Central. * 1.1.2 added support for handling multi-line results, like for example /file print. * 1.1 added TLS (SSL) support to encrypt API traffic. +The latest development version is 2.0.0 which is available using the 2.0.0 branch. + +* Changed ResultListener to receive errors and completion notifications. + Getting the API --------------- @@ -116,7 +120,7 @@ Asynchronous commands We can run some commands asynchronously in order to continue receiving updates: -This example shows how to run '/interface wireless monitor' and have the result sent to a listener object, which prints it +This example shows how to run '/interface wireless monitor' and have the result sent to a listener object, which prints it: ```java String tag = con.execute("/interface/wireless/monitor .id=wlan1 return signal-to-noise", @@ -125,6 +129,14 @@ String tag = con.execute("/interface/wireless/monitor .id=wlan1 return signal-to public void receive(Map result) { System.out.println(result); } + + public void error(MikrotikApiException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + + public void completed() { + System.out.println("Asynchronous command has finished"); + } } ); @@ -136,6 +148,8 @@ The above command will run and send results asynchronously as they become availa con.cancel(tag); ``` +From version 2.0.0 of the API the error() and completed() methods are part of the ResultListener interface. + References ==========