Added pushing asynch

This commit is contained in:
Sven Kubiak 2020-07-27 09:22:49 +02:00
parent 7c3fa73afe
commit b99be4f5fd
6 changed files with 127 additions and 12 deletions

View File

@ -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;
}

View File

@ -4,11 +4,15 @@ import java.io.IOException;
import java.util.NavigableMap; import java.util.NavigableMap;
import java.util.Objects; import java.util.Objects;
import java.util.TreeMap; 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.Param;
import de.svenkubiak.jpushover.enums.Url; import de.svenkubiak.jpushover.enums.Url;
import de.svenkubiak.jpushover.http.PushoverRequest; import de.svenkubiak.jpushover.http.PushoverRequest;
import de.svenkubiak.jpushover.http.PushoverResponse; import de.svenkubiak.jpushover.http.PushoverResponse;
import de.svenkubiak.jpushover.services.AsyncExecutor;
import de.svenkubiak.jpushover.services.AsyncService;
import de.svenkubiak.jpushover.utils.Validate; import de.svenkubiak.jpushover.utils.Validate;
/** /**
@ -16,7 +20,7 @@ import de.svenkubiak.jpushover.utils.Validate;
* @author svenkubiak * @author svenkubiak
* *
*/ */
public class Glance { public class Glance implements API {
private NavigableMap<String, String> body = new TreeMap<>(); private NavigableMap<String, String> body = new TreeMap<>();
private String proxyHost; private String proxyHost;
private int proxyPort; private int proxyPort;
@ -28,7 +32,7 @@ public class Glance {
* @param token The pushover API token * @param token The pushover API token
* @return Glance instance * @return Glance instance
*/ */
public Glance withToken(String token) { public API withToken(String token) {
Objects.requireNonNull(token, "token can not be null"); Objects.requireNonNull(token, "token can not be null");
body.put(Param.TOKEN.toString(), token); body.put(Param.TOKEN.toString(), token);
@ -43,7 +47,7 @@ public class Glance {
* @param user The username * @param user The username
* @return Glance instance * @return Glance instance
*/ */
public Glance withUser(String user) { public API withUser(String user) {
Objects.requireNonNull(user, "user can not be null"); Objects.requireNonNull(user, "user can not be null");
body.put(Param.USER.toString(), user); body.put(Param.USER.toString(), user);
@ -58,7 +62,7 @@ public class Glance {
* @param device The device name * @param device The device name
* @return Glance instance * @return Glance instance
*/ */
public Glance withDevice(String device) { public API withDevice(String device) {
Objects.requireNonNull(device, "device can not be null"); Objects.requireNonNull(device, "device can not be null");
body.put(Param.DEVICE.toString(), device); body.put(Param.DEVICE.toString(), device);
@ -71,7 +75,7 @@ public class Glance {
* @param title the title to use * @param title the title to use
* @return Glance instance * @return Glance instance
*/ */
public Glance withTitle(String title) { public API withTitle(String title) {
Objects.requireNonNull(title, "title can not be null"); Objects.requireNonNull(title, "title can not be null");
Validate.checkArgument(title.length() <= 100, "Title must not exceed a length of 100 characters"); 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 * @param text the text to use
* @return Glance instance * @return Glance instance
*/ */
public Glance withText(String text) { public API withText(String text) {
Objects.requireNonNull(text, "text can not be null"); Objects.requireNonNull(text, "text can not be null");
Validate.checkArgument(text.length() <= 100, "Text must not exceed a length of 100 characters"); 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 * @param subtext the subtext to use
* @return Glance instance * @return Glance instance
*/ */
public Glance withSubtext(String subtext) { public API withSubtext(String subtext) {
Objects.requireNonNull(subtext, "subtext can not be null"); Objects.requireNonNull(subtext, "subtext can not be null");
Validate.checkArgument(subtext.length() <= 100, "Subtext must not exceed a length of 100 characters"); 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 * @param count the count to use
* @return Glance instance * @return Glance instance
*/ */
public Glance withCount(int count) { public API withCount(int count) {
body.put(Param.COUNT.toString(), String.valueOf(count)); body.put(Param.COUNT.toString(), String.valueOf(count));
return this; return this;
} }
@ -124,7 +128,7 @@ public class Glance {
* @param percent the percent to use * @param percent the percent to use
* @return GLance instance * @return GLance instance
*/ */
public Glance withPercent(int percent) { public API withPercent(int percent) {
body.put(Param.PERCENT.toString(), String.valueOf(percent)); body.put(Param.PERCENT.toString(), String.valueOf(percent));
return this; return this;
} }
@ -137,10 +141,27 @@ public class Glance {
* @throws IOException if sending the message fails * @throws IOException if sending the message fails
* @throws InterruptedException if sending the message fails * @throws InterruptedException if sending the message fails
*/ */
@Override
public PushoverResponse push() throws IOException, InterruptedException { public PushoverResponse push() throws IOException, InterruptedException {
Objects.requireNonNull(body.get(Param.TOKEN.toString()), "Token is required for a glance"); 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"); 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); 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<PushoverResponse> 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));
}
} }

View File

@ -4,6 +4,8 @@ import java.io.IOException;
import java.util.NavigableMap; import java.util.NavigableMap;
import java.util.Objects; import java.util.Objects;
import java.util.TreeMap; 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.Param;
import de.svenkubiak.jpushover.enums.Priority; 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.enums.Url;
import de.svenkubiak.jpushover.http.PushoverRequest; import de.svenkubiak.jpushover.http.PushoverRequest;
import de.svenkubiak.jpushover.http.PushoverResponse; import de.svenkubiak.jpushover.http.PushoverResponse;
import de.svenkubiak.jpushover.services.AsyncExecutor;
import de.svenkubiak.jpushover.services.AsyncService;
import de.svenkubiak.jpushover.utils.Validate; import de.svenkubiak.jpushover.utils.Validate;
/** /**
@ -18,7 +22,7 @@ import de.svenkubiak.jpushover.utils.Validate;
* @author svenkubiak * @author svenkubiak
* *
*/ */
public class Message { public class Message implements API {
private NavigableMap<String, String> body = new TreeMap<>(); private NavigableMap<String, String> body = new TreeMap<>();
private String proxyHost; private String proxyHost;
private int proxyPort; private int proxyPort;
@ -271,6 +275,7 @@ public class Message {
* @throws IOException if sending the message fails * @throws IOException if sending the message fails
* @throws InterruptedException if sending the message fails * @throws InterruptedException if sending the message fails
*/ */
@Override
public final PushoverResponse push() throws IOException, InterruptedException { public final PushoverResponse push() throws IOException, InterruptedException {
Objects.requireNonNull(body.get(Param.TOKEN.toString()), "Token is required for validation"); Objects.requireNonNull(body.get(Param.TOKEN.toString()), "Token is required for validation");
Objects.requireNonNull(body.get(Param.USER.toString()), "User 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); 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<PushoverResponse> 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));
}
} }

View File

@ -44,11 +44,9 @@ public class PushoverRequest {
.timeout(Duration.ofSeconds(5)) .timeout(Duration.ofSeconds(5))
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body)) .POST(HttpRequest.BodyPublishers.ofString(body))
.version(HttpClient.Version.HTTP_1_1)
.build(); .build();
var httpClientBuilder = HttpClient.newBuilder(); var httpClientBuilder = HttpClient.newBuilder();
httpClientBuilder.version(HttpClient.Version.HTTP_1_1);
if (proxyHost != null && proxyPort > 0) { if (proxyHost != null && proxyPort > 0) {
httpClientBuilder.proxy(ProxySelector.of(new InetSocketAddress(proxyHost, proxyPort))); httpClientBuilder.proxy(ProxySelector.of(new InetSocketAddress(proxyHost, proxyPort)));

View File

@ -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<T> implements Callable<PushoverResponse> {
private API api;
public AsyncExecutor(API api) {
this.api = api;
}
@Override
public PushoverResponse call() throws Exception {
return api.push();
}
}

View File

@ -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<T> {
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<PushoverResponse> execute(AsyncExecutor<PushoverResponse> asyncExecutor) throws InterruptedException, ExecutionException {
return executorService.submit(asyncExecutor);
}
public void shutdown() {
if (executorService != null) {
executorService.shutdown();
}
}
}