Skip to content

Commit 9ae8c9f

Browse files
committed
Add client copy of SSE to android
1 parent bebf6be commit 9ae8c9f

18 files changed

+1053
-14
lines changed

src/AndroidClient/android/src/main/java/net/servicestack/client/JsonServiceClient.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,19 @@ public class JsonServiceClient implements ServiceClient {
4646
Gson gson;
4747

4848
public JsonServiceClient(String baseUrl) {
49-
this.baseUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
50-
this.replyUrl = this.baseUrl + "json/reply/";
49+
setBaseUrl(baseUrl);
5150

5251
//Automatically populate response cookies
5352
if (CookieHandler.getDefault() == null){
5453
CookieHandler.setDefault(new CookieManager());
5554
}
5655
}
5756

57+
public void setBaseUrl(String baseUrl) {
58+
this.baseUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
59+
this.replyUrl = this.baseUrl + "json/reply/";
60+
}
61+
5862
public void setTimeout(int timeoutMs) {
5963
this.timeoutMs = timeoutMs;
6064
}
@@ -71,7 +75,7 @@ public GsonBuilder getGsonBuilder() {
7175

7276
public Gson getGson() {
7377
if (gson == null) {
74-
gson = getGsonBuilder().create();
78+
gson = getGsonBuilder().disableHtmlEscaping().create();
7579
}
7680
return gson;
7781
}
@@ -317,9 +321,10 @@ public <TResponse> TResponse send(String url, String httpMethod, Object request,
317321

318322
public <TResponse> TResponse send(String requestUrl, String httpMethod, byte[] requestBody, String requestType, Object responseClass) {
319323
HttpURLConnection req = null;
324+
Class resClass = null;
320325
try {
321326
req = createRequest(requestUrl, httpMethod, requestBody, requestType);
322-
Class resClass = responseClass instanceof Class ? (Class)responseClass : null;
327+
resClass = responseClass instanceof Class ? (Class)responseClass : null;
323328
Type resType = responseClass instanceof Type ? (Type)responseClass : null;
324329
if (resClass == null && resType == null)
325330
throw new RuntimeException("responseClass '" + responseClass.getClass().getSimpleName() + "' must be a Class or Type");
@@ -364,6 +369,8 @@ public <TResponse> TResponse send(String requestUrl, String httpMethod, byte[] r
364369
return (TResponse)Utils.readBytesToEnd(req);
365370
if (resClass == String.class)
366371
return (TResponse)Utils.readToEnd(is, UTF8.name());
372+
if (resClass == InputStream.class)
373+
return (TResponse)is;
367374

368375
if (Log.isDebugEnabled()) {
369376
String json = Utils.readToEnd(is, UTF8.name());
@@ -388,7 +395,7 @@ public <TResponse> TResponse send(String requestUrl, String httpMethod, byte[] r
388395
throw new RuntimeException(e);
389396
}
390397
finally {
391-
if (req != null)
398+
if (req != null && resClass != InputStream.class)
392399
req.disconnect();
393400
}
394401
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package net.servicestack.client;
2+
3+
import com.google.gson.JsonElement;
4+
import com.google.gson.JsonObject;
5+
import com.google.gson.JsonParser;
6+
7+
import java.util.HashMap;
8+
import java.util.Map;
9+
10+
/**
11+
* Created by mythz on 2/10/2017.
12+
*/
13+
14+
public class JsonUtils {
15+
16+
public static JsonObject toJsonObject(String json) {
17+
JsonElement e = new JsonParser().parse(json);
18+
if (e.isJsonObject()) {
19+
return e.getAsJsonObject();
20+
}
21+
return null;
22+
}
23+
24+
public static String asString(JsonObject obj, String key) {
25+
if (obj == null)
26+
return null;
27+
if (key == null)
28+
throw new IllegalArgumentException("key is null");
29+
30+
return asString(obj.get(key));
31+
}
32+
33+
public static String asString(JsonElement el)
34+
{
35+
return el != null
36+
? el.getAsString()
37+
: null;
38+
}
39+
40+
public static long asLong(JsonObject obj, String key) {
41+
return asLong(obj, key, 0);
42+
}
43+
44+
public static long asLong(JsonObject obj, String key, long defaultValue) {
45+
if (obj == null)
46+
return defaultValue;
47+
if (key == null)
48+
throw new IllegalArgumentException("key is null");
49+
50+
JsonElement val = obj.get(key);
51+
52+
return val != null
53+
? val.getAsLong()
54+
: defaultValue;
55+
}
56+
}

src/AndroidClient/android/src/main/java/net/servicestack/client/Utils.java

Lines changed: 108 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,20 @@
2121
import java.lang.reflect.Field;
2222
import java.lang.reflect.Modifier;
2323
import java.net.HttpURLConnection;
24+
import java.net.URL;
25+
import java.net.URLConnection;
26+
import java.net.URLEncoder;
2427
import java.nio.ByteBuffer;
2528
import java.text.SimpleDateFormat;
2629
import java.util.ArrayList;
2730
import java.util.Arrays;
2831
import java.util.Calendar;
2932
import java.util.Date;
3033
import java.util.HashMap;
34+
import java.util.Iterator;
3135
import java.util.List;
3236
import java.util.Map;
37+
import java.util.Objects;
3338
import java.util.UUID;
3439

3540
import static net.servicestack.func.Func.last;
@@ -53,7 +58,7 @@ public static Double tryParseDouble(String str) {
5358
}
5459
}
5560

56-
static final String KotlinAnnotationClass = "kotlin.Metadata";
61+
static final String KotlinAnnotationClass = "kotlin.jvm.internal.KotlinClass";
5762

5863
public static boolean isKotlinClass(Class type)
5964
{
@@ -394,6 +399,21 @@ else if (parts.length == 2)
394399
}
395400

396401
/*String Utils*/
402+
public static boolean isEmpty(final String string)
403+
{
404+
return string == null || string.length() == 0;
405+
}
406+
407+
public static boolean isNullOrEmpty(final String string)
408+
{
409+
return string == null || string.length() == 0;
410+
}
411+
412+
public static boolean isNullOrWhiteSpace(final String string)
413+
{
414+
return string == null || string.length() == 0 || string.trim().length() == 0;
415+
}
416+
397417
public static String[] splitOnFirst(String strVal, char needle) {
398418
return splitOnFirst(strVal, needle, 0);
399419
}
@@ -475,6 +495,16 @@ public static byte[] toUtf8Bytes(String string) {
475495
}
476496
}
477497

498+
public static String readToEnd(String url) {
499+
try {
500+
URL heartbeatUrl = new URL(url);
501+
HttpURLConnection conn = (HttpURLConnection)heartbeatUrl.openConnection();
502+
return readToEnd(conn);
503+
} catch (Exception e) {
504+
throw new RuntimeException(e);
505+
}
506+
}
507+
478508
public static String readToEnd(HttpURLConnection response){
479509
try {
480510
return readToEnd(response.getInputStream(), "UTF-8");
@@ -548,11 +578,11 @@ public static ResponseStatus createResponseStatus(JsonObject obj) {
548578
Object field = obj.get(key);
549579

550580
if (varName.toLowerCase().equals("errorcode")) {
551-
status.setErrorCode(jsonElementEntry.getValue().getAsString());
581+
status.setErrorCode(getAsStringOrNull(jsonElementEntry.getValue()));
552582
} else if (varName.toLowerCase().equals("message")) {
553-
status.setMessage(jsonElementEntry.getValue().getAsString());
583+
status.setMessage(getAsStringOrNull(jsonElementEntry.getValue()));
554584
} else if (varName.toLowerCase().equals("stacktrace")) {
555-
status.setStackTrace(jsonElementEntry.getValue().getAsString());
585+
status.setStackTrace(getAsStringOrNull(jsonElementEntry.getValue()));
556586
} else if (varName.toLowerCase().equals("errors")) {
557587

558588
if (field instanceof JsonArray){
@@ -567,11 +597,11 @@ public static ResponseStatus createResponseStatus(JsonObject obj) {
567597
String fieldName = Utils.sanitizeVarName(fieldKey);
568598

569599
if (fieldName.toLowerCase().equals("errorcode")) {
570-
fieldError.setErrorCode(entry.getValue().getAsString());
600+
fieldError.setErrorCode(getAsStringOrNull(entry.getValue()));
571601
} else if (fieldName.toLowerCase().equals("message")) {
572-
fieldError.setMessage(entry.getValue().getAsString());
602+
fieldError.setMessage(getAsStringOrNull(entry.getValue()));
573603
} else if (fieldName.toLowerCase().equals("fieldname")) {
574-
fieldError.setFieldName(entry.getValue().getAsString());
604+
fieldError.setFieldName(getAsStringOrNull(entry.getValue()));
575605
}
576606

577607
}
@@ -729,6 +759,10 @@ public static byte[] toBase64Bytes(byte[] source, int off, int len) {
729759
}
730760
}
731761

762+
private static String getAsStringOrNull(JsonElement jsonElement) {
763+
return jsonElement.isJsonNull() ? null : jsonElement.getAsString();
764+
}
765+
732766
private final static byte EQUALS_SIGN = (byte)'=';
733767

734768
private final static byte[] _STANDARD_ALPHABET = {
@@ -782,4 +816,71 @@ private static byte[] encode3to4(
782816
}
783817
}
784818

819+
public static String addQueryParam(String url, String key, String value) {
820+
return addQueryParam(url, key, value, true);
821+
}
822+
823+
public static String addQueryParam(String url, String key, String val, boolean encode) {
824+
if (url == null || url.length() == 0)
825+
return null;
826+
String prefix = "";
827+
if (!url.endsWith("?") && !url.endsWith("&")) {
828+
prefix = url.indexOf('?') == -1 ? "?" : "&";
829+
}
830+
try {
831+
return url + prefix + key + "=" + (encode && val != null ? URLEncoder.encode(val, "UTF-8") : val);
832+
} catch (UnsupportedEncodingException e) {
833+
throw new RuntimeException(e);
834+
}
835+
}
836+
837+
public static final String EMPTY = "";
838+
839+
public static String toString(Object o, String nullDefault) {
840+
return (o != null) ? o.toString() : nullDefault;
841+
}
842+
843+
public static String join(final String[] array, final String separator) {
844+
if (array == null)
845+
return null;
846+
847+
return join(Arrays.asList(array), separator);
848+
}
849+
850+
public static String join(final Iterable<?> iterable, final String separator) {
851+
if (iterable == null) {
852+
return null;
853+
}
854+
return join(iterable.iterator(), separator);
855+
}
856+
857+
public static String join(final Iterator<?> iterator, final String separator) {
858+
if (iterator == null) {
859+
return null;
860+
}
861+
if (!iterator.hasNext()) {
862+
return EMPTY;
863+
}
864+
final Object first = iterator.next();
865+
if (!iterator.hasNext()) {
866+
final String result = toString(first, "");
867+
return result;
868+
}
869+
870+
final StringBuilder buf = new StringBuilder(256);
871+
if (first != null) {
872+
buf.append(first);
873+
}
874+
875+
while (iterator.hasNext()) {
876+
if (separator != null) {
877+
buf.append(separator);
878+
}
879+
final Object obj = iterator.next();
880+
if (obj != null) {
881+
buf.append(obj);
882+
}
883+
}
884+
return buf.toString();
885+
}
785886
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package net.servicestack.client.sse;
2+
3+
/**
4+
* Created by mythz on 2/10/2017.
5+
*/
6+
7+
public interface ExceptionCallback {
8+
void execute(Exception ex);
9+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package net.servicestack.client.sse;
2+
3+
import java.net.HttpURLConnection;
4+
5+
/**
6+
* Created by mythz on 2/10/2017.
7+
*/
8+
9+
public interface HttpRequestFilter {
10+
void execute(HttpURLConnection req);
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package net.servicestack.client.sse;
2+
3+
import java.net.HttpURLConnection;
4+
5+
/**
6+
* Created by mythz on 2/10/2017.
7+
*/
8+
9+
public interface HttpResponseFilter {
10+
void execute(HttpURLConnection req);
11+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package net.servicestack.client.sse;
2+
3+
/**
4+
* Created by mythz on 2/10/2017.
5+
*/
6+
7+
public interface ServerEventCallback {
8+
void execute(ServerEventsClient client, ServerEventMessage e);
9+
}

0 commit comments

Comments
 (0)