diff --git a/lib/src/main/java/com/nextcloud/android/sso/api/AidlNetworkRequest.java b/lib/src/main/java/com/nextcloud/android/sso/api/AidlNetworkRequest.java index 776e7361..f2e10073 100644 --- a/lib/src/main/java/com/nextcloud/android/sso/api/AidlNetworkRequest.java +++ b/lib/src/main/java/com/nextcloud/android/sso/api/AidlNetworkRequest.java @@ -98,7 +98,7 @@ public void connect(String type) { try { final Intent intentService = new Intent(); intentService.setComponent(new ComponentName(componentName, - "com.owncloud.android.services.AccountManagerService")); + "com.owncloud.android.services.AccountManagerService")); // https://developer.android.com/reference/android/content/Context#BIND_ABOVE_CLIENT if (!mContext.bindService(intentService, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_ABOVE_CLIENT)) { Log.d(TAG, "[connect] Binding to AccountManagerService returned false"); @@ -171,14 +171,14 @@ public Response performNetworkRequestV2(NextcloudRequest request, InputStream re final ParcelFileDescriptor output = performAidlNetworkRequestV2(request, requestBodyInputStream); final InputStream os = new ParcelFileDescriptor.AutoCloseInputStream(output); try { - final ExceptionResponse response = deserializeObjectV2(os); + final var response = deserializeObjectV2(os); // Handle Remote Exceptions - if (response.getException() != null) { - if (response.getException().getMessage() != null) { - throw parseNextcloudCustomException(mContext, response.getException()); + if (response.exception() != null) { + if (response.exception().getMessage() != null) { + throw parseNextcloudCustomException(mContext, response.exception()); } - throw response.getException(); + throw response.exception(); } // os stream needs to stay open to be able to read response return new Response(os, response.headers); @@ -192,9 +192,8 @@ public Response performNetworkRequestV2(NextcloudRequest request, InputStream re /** * DO NOT CALL THIS METHOD DIRECTLY - use {@link #performNetworkRequestV2} instead * - * @param request - * @return - * @throws IOException + * @param request, requestBodyInputStream + * @throws IOException, RemoteException, NextcloudApiNotRespondingException */ private ParcelFileDescriptor performAidlNetworkRequestV2(@NonNull NextcloudRequest request, @Nullable InputStream requestBodyInputStream) @@ -245,7 +244,7 @@ private ExceptionResponse deserializeObjectV2(InputStream is) throws IOException } } - return new ExceptionResponse(exception, headerList); + return new ExceptionResponse(headerList, exception); } public static class PlainHeader implements Serializable { @@ -276,17 +275,9 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE } } - private static class ExceptionResponse { - private final Exception exception; - private final ArrayList headers; - - public ExceptionResponse(Exception exception, ArrayList headers) { - this.exception = exception; - this.headers = headers; - } - - public Exception getException() { - return exception; - } + private record ExceptionResponse( + @NonNull ArrayList headers, + @Nullable Exception exception + ) { } } diff --git a/lib/src/main/java/com/nextcloud/android/sso/exceptions/SSOException.java b/lib/src/main/java/com/nextcloud/android/sso/exceptions/SSOException.java index 5f3f66e0..fc9cb42f 100644 --- a/lib/src/main/java/com/nextcloud/android/sso/exceptions/SSOException.java +++ b/lib/src/main/java/com/nextcloud/android/sso/exceptions/SSOException.java @@ -88,23 +88,20 @@ public static SSOException parseNextcloudCustomException(@NonNull Context contex return new UnknownErrorException("Exception message is null"); } - switch (message) { - case Constants.EXCEPTION_INVALID_TOKEN: - return new TokenMismatchException(context); - case Constants.EXCEPTION_ACCOUNT_NOT_FOUND: - return new NextcloudFilesAppAccountNotFoundException(context); - case Constants.EXCEPTION_UNSUPPORTED_METHOD: - return new NextcloudUnsupportedMethodException(context); - case Constants.EXCEPTION_INVALID_REQUEST_URL: - return new NextcloudInvalidRequestUrlException(context, exception.getCause()); - case Constants.EXCEPTION_HTTP_REQUEST_FAILED: + return switch (message) { + case Constants.EXCEPTION_INVALID_TOKEN -> new TokenMismatchException(context); + case Constants.EXCEPTION_ACCOUNT_NOT_FOUND -> new NextcloudFilesAppAccountNotFoundException(context); + case Constants.EXCEPTION_UNSUPPORTED_METHOD -> new NextcloudUnsupportedMethodException(context); + case Constants.EXCEPTION_INVALID_REQUEST_URL -> + new NextcloudInvalidRequestUrlException(context, exception.getCause()); + case Constants.EXCEPTION_HTTP_REQUEST_FAILED -> { final int statusCode = Integer.parseInt(exception.getCause().getMessage()); final var cause = exception.getCause().getCause(); - return new NextcloudHttpRequestFailedException(context, statusCode, cause); - case Constants.EXCEPTION_ACCOUNT_ACCESS_DECLINED: - return new NextcloudFilesAppAccountPermissionNotGrantedException(context); - default: - return new UnknownErrorException(exception.getMessage()); - } + yield new NextcloudHttpRequestFailedException(context, statusCode, cause); + } + case Constants.EXCEPTION_ACCOUNT_ACCESS_DECLINED -> + new NextcloudFilesAppAccountPermissionNotGrantedException(context); + default -> new UnknownErrorException(exception.getMessage()); + }; } } diff --git a/lib/src/main/java/com/nextcloud/android/sso/helper/Retrofit2Helper.java b/lib/src/main/java/com/nextcloud/android/sso/helper/Retrofit2Helper.java index 31f09559..23f6b177 100644 --- a/lib/src/main/java/com/nextcloud/android/sso/helper/Retrofit2Helper.java +++ b/lib/src/main/java/com/nextcloud/android/sso/helper/Retrofit2Helper.java @@ -13,22 +13,20 @@ import androidx.annotation.NonNull; import com.nextcloud.android.sso.aidl.NextcloudRequest; -import com.nextcloud.android.sso.api.EmptyResponse; import com.nextcloud.android.sso.api.AidlNetworkRequest; import com.nextcloud.android.sso.api.NextcloudAPI; import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException; import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; +import java.util.Arrays; +import java.util.Collections; +import java.util.Optional; +import java.util.stream.Collectors; import okhttp3.Headers; -import okhttp3.MediaType; import okhttp3.Protocol; import okhttp3.Request; import okhttp3.ResponseBody; -import okio.BufferedSource; import okio.Timeout; import retrofit2.Call; import retrofit2.Callback; @@ -36,9 +34,11 @@ public final class Retrofit2Helper { - private Retrofit2Helper() { } + private Retrofit2Helper() { + } - public static Call WrapInCall(final NextcloudAPI nextcloudAPI, final NextcloudRequest nextcloudRequest, + public static Call WrapInCall(final NextcloudAPI nextcloudAPI, + final NextcloudRequest nextcloudRequest, final Type resType) { return new Call<>() { @@ -49,22 +49,23 @@ public static Call WrapInCall(final NextcloudAPI nextcloudAPI, final Next @Override public Response execute() { try { - com.nextcloud.android.sso.api.Response response = nextcloudAPI.performNetworkRequestV2(nextcloudRequest); - - T body = nextcloudAPI.convertStreamToTargetEntity(response.getBody(), resType); - Map headerMap = new HashMap<>(); - ArrayList plainHeaders = response.getPlainHeaders(); - if (plainHeaders != null) { - for (AidlNetworkRequest.PlainHeader header : plainHeaders) { - headerMap.put(header.getName(), header.getValue()); - } - } + final var response = nextcloudAPI.performNetworkRequestV2(nextcloudRequest); + final T body = nextcloudAPI.convertStreamToTargetEntity(response.getBody(), resType); + final var headerMap = Optional.ofNullable(response.getPlainHeaders()) + .map(headers -> headers + .stream() + .collect(Collectors.toMap( + AidlNetworkRequest.PlainHeader::getName, + AidlNetworkRequest.PlainHeader::getValue))) + .orElse(Collections.emptyMap()); + return Response.success(body, Headers.of(headerMap)); + } catch (NextcloudHttpRequestFailedException e) { - final Throwable cause = e.getCause(); - return convertExceptionToResponse(e.getStatusCode(), cause == null ? e.getMessage() : cause.getMessage()); + return convertExceptionToResponse(e.getStatusCode(), Optional.ofNullable(e.getCause()).orElse(e)); + } catch (Exception e) { - return convertExceptionToResponse(520, e.toString()); + return convertExceptionToResponse(900, e); } } @@ -73,8 +74,7 @@ public Response execute() { */ @Override public void enqueue(@NonNull final Callback callback) { - final Call call = this; - new Thread(() -> callback.onResponse(call, execute())).start(); + new Thread(() -> callback.onResponse(this, execute())).start(); } @Override @@ -110,17 +110,19 @@ public Timeout timeout() { throw new UnsupportedOperationException("Not implemented"); } - private Response convertExceptionToResponse(int statusCode, String errorMessage) { - ResponseBody body = ResponseBody.create(null, errorMessage); + private Response convertExceptionToResponse(int statusCode, @NonNull Throwable throwable) { + final var body = ResponseBody.create(null, throwable.toString()); + final var path = Optional.ofNullable(nextcloudRequest.getUrl()).orElse(""); + return Response.error( - body, - new okhttp3.Response.Builder() - .body(body) - .code(statusCode) - .message(errorMessage) - .protocol(Protocol.HTTP_1_1) - .request(new Request.Builder().url("http://localhost/" + nextcloudRequest.getUrl()).build()) - .build()); + body, + new okhttp3.Response.Builder() + .body(body) + .code(statusCode) + .message(throwable.getMessage() + Arrays.toString(throwable.getStackTrace())) + .protocol(Protocol.HTTP_1_1) + .request(new Request.Builder().url("http://example.com" + (path.startsWith("/") ? path : "/" + path)).build()) + .build()); } }; }