From b99be4f5fd23886a2550a145cab78d059bf2996d Mon Sep 17 00:00:00 2001 From: Sven Kubiak Date: Mon, 27 Jul 2020 09:22:49 +0200 Subject: [PATCH] Added pushing asynch --- .../de/svenkubiak/jpushover/apis/API.java | 14 +++++++ .../de/svenkubiak/jpushover/apis/Glance.java | 39 ++++++++++++++----- .../de/svenkubiak/jpushover/apis/Message.java | 23 ++++++++++- .../jpushover/http/PushoverRequest.java | 2 - .../jpushover/services/AsyncExecutor.java | 24 ++++++++++++ .../jpushover/services/AsyncService.java | 37 ++++++++++++++++++ 6 files changed, 127 insertions(+), 12 deletions(-) create mode 100644 src/main/java/de/svenkubiak/jpushover/apis/API.java create mode 100644 src/main/java/de/svenkubiak/jpushover/services/AsyncExecutor.java create mode 100644 src/main/java/de/svenkubiak/jpushover/services/AsyncService.java diff --git a/src/main/java/de/svenkubiak/jpushover/apis/API.java b/src/main/java/de/svenkubiak/jpushover/apis/API.java new file mode 100644 index 0000000..4270902 --- /dev/null +++ b/src/main/java/de/svenkubiak/jpushover/apis/API.java @@ -0,0 +1,14 @@ +package de.svenkubiak.jpushover.apis; + +import java.io.IOException; + +import de.svenkubiak.jpushover.http.PushoverResponse; + +/** + * + * @author svenkubiak + * + */ +public interface API { + PushoverResponse push() throws IOException, InterruptedException; +} \ No newline at end of file diff --git a/src/main/java/de/svenkubiak/jpushover/apis/Glance.java b/src/main/java/de/svenkubiak/jpushover/apis/Glance.java index 5c33411..02f4563 100644 --- a/src/main/java/de/svenkubiak/jpushover/apis/Glance.java +++ b/src/main/java/de/svenkubiak/jpushover/apis/Glance.java @@ -4,11 +4,15 @@ import java.io.IOException; import java.util.NavigableMap; import java.util.Objects; import java.util.TreeMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import de.svenkubiak.jpushover.enums.Param; import de.svenkubiak.jpushover.enums.Url; import de.svenkubiak.jpushover.http.PushoverRequest; import de.svenkubiak.jpushover.http.PushoverResponse; +import de.svenkubiak.jpushover.services.AsyncExecutor; +import de.svenkubiak.jpushover.services.AsyncService; import de.svenkubiak.jpushover.utils.Validate; /** @@ -16,7 +20,7 @@ import de.svenkubiak.jpushover.utils.Validate; * @author svenkubiak * */ -public class Glance { +public class Glance implements API { private NavigableMap body = new TreeMap<>(); private String proxyHost; private int proxyPort; @@ -28,7 +32,7 @@ public class Glance { * @param token The pushover API token * @return Glance instance */ - public Glance withToken(String token) { + public API withToken(String token) { Objects.requireNonNull(token, "token can not be null"); body.put(Param.TOKEN.toString(), token); @@ -43,7 +47,7 @@ public class Glance { * @param user The username * @return Glance instance */ - public Glance withUser(String user) { + public API withUser(String user) { Objects.requireNonNull(user, "user can not be null"); body.put(Param.USER.toString(), user); @@ -58,7 +62,7 @@ public class Glance { * @param device The device name * @return Glance instance */ - public Glance withDevice(String device) { + public API withDevice(String device) { Objects.requireNonNull(device, "device can not be null"); body.put(Param.DEVICE.toString(), device); @@ -71,7 +75,7 @@ public class Glance { * @param title the title to use * @return Glance instance */ - public Glance withTitle(String title) { + public API withTitle(String title) { Objects.requireNonNull(title, "title can not be null"); Validate.checkArgument(title.length() <= 100, "Title must not exceed a length of 100 characters"); @@ -85,7 +89,7 @@ public class Glance { * @param text the text to use * @return Glance instance */ - public Glance withText(String text) { + public API withText(String text) { Objects.requireNonNull(text, "text can not be null"); Validate.checkArgument(text.length() <= 100, "Text must not exceed a length of 100 characters"); @@ -99,7 +103,7 @@ public class Glance { * @param subtext the subtext to use * @return Glance instance */ - public Glance withSubtext(String subtext) { + public API withSubtext(String subtext) { Objects.requireNonNull(subtext, "subtext can not be null"); Validate.checkArgument(subtext.length() <= 100, "Subtext must not exceed a length of 100 characters"); @@ -113,7 +117,7 @@ public class Glance { * @param count the count to use * @return Glance instance */ - public Glance withCount(int count) { + public API withCount(int count) { body.put(Param.COUNT.toString(), String.valueOf(count)); return this; } @@ -124,7 +128,7 @@ public class Glance { * @param percent the percent to use * @return GLance instance */ - public Glance withPercent(int percent) { + public API withPercent(int percent) { body.put(Param.PERCENT.toString(), String.valueOf(percent)); return this; } @@ -137,10 +141,27 @@ public class Glance { * @throws IOException if sending the message fails * @throws InterruptedException if sending the message fails */ + @Override public PushoverResponse push() throws IOException, InterruptedException { Objects.requireNonNull(body.get(Param.TOKEN.toString()), "Token is required for a glance"); Objects.requireNonNull(body.get(Param.USER.toString()), "User is required for a glance"); return new PushoverRequest().push(Url.GLANCES.toString(), body, this.proxyHost, this.proxyPort); } + + /** + * Sends a glance to pushover asynchronously + * + * @return PushoverResponse instance + * + * @throws IOException if sending the message fails + * @throws InterruptedException if sending the message fails + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public Future pushAsync() throws InterruptedException, ExecutionException { + Objects.requireNonNull(body.get(Param.TOKEN.toString()), "Token is required for a glance"); + Objects.requireNonNull(body.get(Param.USER.toString()), "User is required for a glance"); + + return AsyncService.getInstance().execute(new AsyncExecutor(this)); + } } \ No newline at end of file diff --git a/src/main/java/de/svenkubiak/jpushover/apis/Message.java b/src/main/java/de/svenkubiak/jpushover/apis/Message.java index eb22f7a..f9e176a 100644 --- a/src/main/java/de/svenkubiak/jpushover/apis/Message.java +++ b/src/main/java/de/svenkubiak/jpushover/apis/Message.java @@ -4,6 +4,8 @@ import java.io.IOException; import java.util.NavigableMap; import java.util.Objects; import java.util.TreeMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import de.svenkubiak.jpushover.enums.Param; import de.svenkubiak.jpushover.enums.Priority; @@ -11,6 +13,8 @@ import de.svenkubiak.jpushover.enums.Sound; import de.svenkubiak.jpushover.enums.Url; import de.svenkubiak.jpushover.http.PushoverRequest; import de.svenkubiak.jpushover.http.PushoverResponse; +import de.svenkubiak.jpushover.services.AsyncExecutor; +import de.svenkubiak.jpushover.services.AsyncService; import de.svenkubiak.jpushover.utils.Validate; /** @@ -18,7 +22,7 @@ import de.svenkubiak.jpushover.utils.Validate; * @author svenkubiak * */ -public class Message { +public class Message implements API { private NavigableMap body = new TreeMap<>(); private String proxyHost; private int proxyPort; @@ -271,6 +275,7 @@ public class Message { * @throws IOException if sending the message fails * @throws InterruptedException if sending the message fails */ + @Override public final PushoverResponse push() throws IOException, InterruptedException { Objects.requireNonNull(body.get(Param.TOKEN.toString()), "Token is required for validation"); Objects.requireNonNull(body.get(Param.USER.toString()), "User is required for validation"); @@ -301,4 +306,20 @@ public class Message { return new PushoverRequest().push(Url.MESSAGES.toString(), body, this.proxyHost, this.proxyPort); } + + /** + * Sends a message to pushover asynchronously + * + * @return PushoverResponse instance + * + * @throws IOException if sending the message fails + * @throws InterruptedException if sending the message fails + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Future pushAsync() throws InterruptedException, ExecutionException { + Objects.requireNonNull(body.get(Param.TOKEN.toString()), "Token is required for a glance"); + Objects.requireNonNull(body.get(Param.USER.toString()), "User is required for a glance"); + + return AsyncService.getInstance().execute(new AsyncExecutor(this)); + } } \ No newline at end of file diff --git a/src/main/java/de/svenkubiak/jpushover/http/PushoverRequest.java b/src/main/java/de/svenkubiak/jpushover/http/PushoverRequest.java index 3bd2aaf..77f406f 100644 --- a/src/main/java/de/svenkubiak/jpushover/http/PushoverRequest.java +++ b/src/main/java/de/svenkubiak/jpushover/http/PushoverRequest.java @@ -44,11 +44,9 @@ public class PushoverRequest { .timeout(Duration.ofSeconds(5)) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(body)) - .version(HttpClient.Version.HTTP_1_1) .build(); var httpClientBuilder = HttpClient.newBuilder(); - httpClientBuilder.version(HttpClient.Version.HTTP_1_1); if (proxyHost != null && proxyPort > 0) { httpClientBuilder.proxy(ProxySelector.of(new InetSocketAddress(proxyHost, proxyPort))); diff --git a/src/main/java/de/svenkubiak/jpushover/services/AsyncExecutor.java b/src/main/java/de/svenkubiak/jpushover/services/AsyncExecutor.java new file mode 100644 index 0000000..15880e2 --- /dev/null +++ b/src/main/java/de/svenkubiak/jpushover/services/AsyncExecutor.java @@ -0,0 +1,24 @@ +package de.svenkubiak.jpushover.services; + +import java.util.concurrent.Callable; + +import de.svenkubiak.jpushover.apis.API; +import de.svenkubiak.jpushover.http.PushoverResponse; + +/** + * + * @author svenkubiak + * + */ +public class AsyncExecutor implements Callable { + private API api; + + public AsyncExecutor(API api) { + this.api = api; + } + + @Override + public PushoverResponse call() throws Exception { + return api.push(); + } +} \ No newline at end of file diff --git a/src/main/java/de/svenkubiak/jpushover/services/AsyncService.java b/src/main/java/de/svenkubiak/jpushover/services/AsyncService.java new file mode 100644 index 0000000..deb4750 --- /dev/null +++ b/src/main/java/de/svenkubiak/jpushover/services/AsyncService.java @@ -0,0 +1,37 @@ +package de.svenkubiak.jpushover.services; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import de.svenkubiak.jpushover.http.PushoverResponse; + +/** + * + * @author svenkubiak + * + */ +public class AsyncService { + private static AsyncService INSTANCE; + private final ExecutorService executorService = Executors.newFixedThreadPool(1); + + @SuppressWarnings("rawtypes") + public static AsyncService getInstance() { + if (INSTANCE == null) { + INSTANCE = new AsyncService(); + } + + return INSTANCE; + } + + public Future execute(AsyncExecutor asyncExecutor) throws InterruptedException, ExecutionException { + return executorService.submit(asyncExecutor); + } + + public void shutdown() { + if (executorService != null) { + executorService.shutdown(); + } + } +} \ No newline at end of file