Commit bed51e93 authored by Tiago Cunha's avatar Tiago Cunha

Trying some Rx spice

parent 8dc3027d
......@@ -8,13 +8,12 @@ import java.io.IOException;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import rx.Emitter;
import rx.Observable;
public class DefaultServerPolicyApi implements ServerPolicyApi {
private static final String SECURE_PROTOCOL = "https://";
private static final String INSECURE_PROTOCOL = "http://";
private static final String API_INFO_PATH = "/api/info";
private final OkHttpClient client;
......@@ -26,13 +25,23 @@ public class DefaultServerPolicyApi implements ServerPolicyApi {
}
@Override
public void getApiInfoSecurely(@NonNull Callback callback) {
client.newCall(createRequest(SECURE_PROTOCOL)).enqueue(getOkHttpCallback(callback));
public Observable<Response<JSONObject>> getApiInfoSecurely() {
return getApiInfo(SECURE_PROTOCOL);
}
@Override
public void getApiInfoInsecurely(@NonNull Callback callback) {
client.newCall(createRequest(INSECURE_PROTOCOL)).enqueue(getOkHttpCallback(callback));
public Observable<Response<JSONObject>> getApiInfoInsecurely() {
return getApiInfo(INSECURE_PROTOCOL);
}
private Observable<Response<JSONObject>> getApiInfo(@NonNull String protocol) {
return Observable.fromEmitter(responseEmitter -> {
final Call call = client.newCall(createRequest(protocol));
call.enqueue(getOkHttpCallback(responseEmitter, protocol));
responseEmitter.setCancellation(call::cancel);
}, Emitter.BackpressureMode.LATEST);
}
private Request createRequest(@NonNull String protocol) {
......@@ -42,31 +51,36 @@ public class DefaultServerPolicyApi implements ServerPolicyApi {
.build();
}
private okhttp3.Callback getOkHttpCallback(@NonNull Callback callback) {
private okhttp3.Callback getOkHttpCallback(@NonNull Emitter<Response<JSONObject>> emitter,
@NonNull String protocol) {
return new okhttp3.Callback() {
@Override
public void onFailure(Call call, IOException ioException) {
callback.onNetworkError();
emitter.onError(ioException);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
public void onResponse(Call call, okhttp3.Response response) throws IOException {
if (!response.isSuccessful()) {
callback.onResponseError();
emitter.onNext(new Response<>(false, protocol, null));
emitter.onCompleted();
return;
}
final ResponseBody body = response.body();
if (body == null || body.contentLength() == 0) {
callback.onResponseError();
emitter.onNext(new Response<>(false, protocol, null));
emitter.onCompleted();
return;
}
try {
callback.onSuccess(new JSONObject(body.string()));
emitter.onNext(new Response<>(true, protocol, new JSONObject(body.string())));
} catch (Exception e) {
callback.onResponseError();
emitter.onNext(new Response<>(false, protocol, null));
}
emitter.onCompleted();
}
};
}
......
package chat.rocket.android.api.rest;
public class Response<T> {
private final boolean successful;
private final String protocol;
private final T data;
public Response(boolean successful, String protocol, T data) {
this.successful = successful;
this.protocol = protocol;
this.data = data;
}
public boolean isSuccessful() {
return successful;
}
public String getProtocol() {
return protocol;
}
public T getData() {
return data;
}
}
package chat.rocket.android.api.rest;
import android.support.annotation.NonNull;
import org.json.JSONObject;
public interface ServerPolicyApi {
void getApiInfoSecurely(@NonNull Callback callback);
import rx.Observable;
void getApiInfoInsecurely(@NonNull Callback callback);
public interface ServerPolicyApi {
interface Callback {
void onSuccess(JSONObject jsonObject);
String SECURE_PROTOCOL = "https://";
String INSECURE_PROTOCOL = "http://";
void onResponseError();
Observable<Response<JSONObject>> getApiInfoSecurely();
void onNetworkError();
}
Observable<Response<JSONObject>> getApiInfoInsecurely();
}
......@@ -11,11 +11,14 @@ import chat.rocket.android.api.rest.DefaultServerPolicyApi;
import chat.rocket.android.api.rest.ServerPolicyApi;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.helper.OkHttpHelper;
import chat.rocket.android.helper.ServerPolicyApiValidationHelper;
import chat.rocket.android.helper.ServerPolicyHelper;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* Input server host.
......@@ -51,28 +54,26 @@ public class InputHostnameFragment extends AbstractServerConfigFragment {
private void handleConnect() {
final String hostname = ServerPolicyHelper.enforceHostname(getHostname());
ServerPolicyApi serverPolicyApi =
final ServerPolicyApi serverPolicyApi =
new DefaultServerPolicyApi(OkHttpHelper.getClientForUploadFile(), hostname);
ServerPolicyHelper.isApiVersionValid(serverPolicyApi,
new ServerPolicyHelper.Callback() {
@Override
public void isValid(boolean usesSecureConnection) {
getActivity().runOnUiThread(() -> onServerValid(hostname, usesSecureConnection));
}
@Override
public void isNotValid() {
getActivity().runOnUiThread(() ->
showError(getString(R.string.input_hostname_invalid_server_message)));
}
@Override
public void onNetworkError() {
getActivity().runOnUiThread(() ->
showError(getString(R.string.connection_error_try_later)));
}
});
final ServerPolicyApiValidationHelper validationHelper =
new ServerPolicyApiValidationHelper(serverPolicyApi);
ServerPolicyHelper.isApiVersionValid(validationHelper)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
serverValidation -> {
if (serverValidation.isValid()) {
onServerValid(hostname, serverValidation.usesSecureConnection());
} else {
showError(getString(R.string.input_hostname_invalid_server_message));
}
},
throwable -> {
showError(getString(R.string.connection_error_try_later));
});
}
@Override
......
......@@ -2,67 +2,23 @@ package chat.rocket.android.helper;
import android.support.annotation.NonNull;
import org.json.JSONObject;
import chat.rocket.android.api.rest.ServerPolicyApi;
import rx.Observable;
public class ServerPolicyApiValidationHelper {
public static void getApiVersion(@NonNull ServerPolicyApi serverPolicyApi,
@NonNull Callback callback) {
trySecurely(serverPolicyApi, new Callback() {
@Override
public void onSuccess(boolean usesSecureConnection, JSONObject apiInfo) {
callback.onSuccess(usesSecureConnection, apiInfo);
}
@Override
public void onResponseError() {
callback.onResponseError();
}
@Override
public void onNetworkError() {
tryInsecurely(serverPolicyApi, callback);
}
});
}
private static void trySecurely(@NonNull ServerPolicyApi serverPolicyApi,
@NonNull Callback callback) {
serverPolicyApi.getApiInfoSecurely(getServerPolicyApiCallback(true, callback));
}
private static void tryInsecurely(@NonNull ServerPolicyApi serverPolicyApi,
@NonNull Callback callback) {
serverPolicyApi.getApiInfoInsecurely(getServerPolicyApiCallback(false, callback));
}
private static ServerPolicyApi.Callback getServerPolicyApiCallback(boolean isSecureConnection,
@NonNull Callback callback) {
return new ServerPolicyApi.Callback() {
@Override
public void onSuccess(JSONObject jsonObject) {
callback.onSuccess(isSecureConnection, jsonObject);
}
private final ServerPolicyApi serverPolicyApi;
@Override
public void onResponseError() {
callback.onResponseError();
}
@Override
public void onNetworkError() {
callback.onNetworkError();
}
};
public ServerPolicyApiValidationHelper(@NonNull ServerPolicyApi serverPolicyApi) {
this.serverPolicyApi = serverPolicyApi;
}
interface Callback {
void onSuccess(boolean usesSecureConnection, JSONObject apiInfo);
void onResponseError();
void onNetworkError();
public Observable<ServerPolicyHelper.ServerInfo> getApiVersion() {
return serverPolicyApi.getApiInfoSecurely()
.onErrorResumeNext(serverPolicyApi.getApiInfoInsecurely())
.map(response -> new ServerPolicyHelper.ServerInfo(
response.getProtocol().equals(ServerPolicyApi.SECURE_PROTOCOL),
response.getData()
));
}
}
......@@ -4,7 +4,7 @@ import android.support.annotation.NonNull;
import org.json.JSONObject;
import chat.rocket.android.api.rest.ServerPolicyApi;
import rx.Observable;
public class ServerPolicyHelper {
......@@ -19,29 +19,12 @@ public class ServerPolicyHelper {
return removeTrailingSlash(removeProtocol(enforceDefaultHost(hostname)));
}
public static void isApiVersionValid(@NonNull ServerPolicyApi serverPolicyApi,
@NonNull Callback callback) {
ServerPolicyApiValidationHelper.getApiVersion(serverPolicyApi,
new ServerPolicyApiValidationHelper.Callback() {
@Override
public void onSuccess(boolean usesSecureConnection, JSONObject apiInfo) {
if (isValid(apiInfo)) {
callback.isValid(usesSecureConnection);
return;
}
callback.isNotValid();
}
@Override
public void onResponseError() {
callback.isNotValid();
}
@Override
public void onNetworkError() {
callback.onNetworkError();
}
});
public static Observable<ServerValidation> isApiVersionValid(
@NonNull ServerPolicyApiValidationHelper serverPolicyApiValidationHelper) {
return serverPolicyApiValidationHelper.getApiVersion()
.map(serverInfo ->
new ServerValidation(isValid(serverInfo.getApiInfo()),
serverInfo.usesSecureConnection()));
}
@NonNull
......@@ -89,11 +72,39 @@ public class ServerPolicyHelper {
return versionParts.length >= 3 && Integer.parseInt(versionParts[1]) >= 49;
}
public interface Callback {
void isValid(boolean usesSecureConnection);
public static class ServerInfo {
private final boolean secureConnection;
private final JSONObject apiInfo;
void isNotValid();
public ServerInfo(boolean secureConnection, JSONObject apiInfo) {
this.secureConnection = secureConnection;
this.apiInfo = apiInfo;
}
public boolean usesSecureConnection() {
return secureConnection;
}
public JSONObject getApiInfo() {
return apiInfo;
}
}
void onNetworkError();
public static class ServerValidation {
private final boolean valid;
private final boolean secureConnection;
public ServerValidation(boolean valid, boolean secureConnection) {
this.valid = valid;
this.secureConnection = secureConnection;
}
public boolean isValid() {
return valid;
}
public boolean usesSecureConnection() {
return secureConnection;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment