Loading build.gradle +5 −0 Original line number Diff line number Diff line Loading @@ -52,4 +52,9 @@ dependencies { implementation 'com.squareup.retrofit2:retrofit:2.3.0' implementation 'com.squareup.okhttp3:okhttp:3.8.0' // Required for local unit tests (JUnit 4 framework) testImplementation 'junit:junit:4.12' // required if you want to use Mockito for unit tests testImplementation 'org.mockito:mockito-core:2.23.4' } src/main/java/com/nextcloud/android/sso/aidl/NextcloudRequest.java +55 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.nextcloud.android.sso.aidl; import android.support.annotation.VisibleForTesting; import java.io.Serializable; import java.util.HashMap; import java.util.List; Loading @@ -40,7 +42,7 @@ public class NextcloudRequest implements Serializable { private NextcloudRequest() { } public static class Builder { public static class Builder implements Cloneable { private NextcloudRequest ncr; public Builder() { Loading Loading @@ -95,6 +97,10 @@ public class NextcloudRequest implements Serializable { ncr.followRedirects = followRedirects; return this; } public Object clone() throws CloneNotSupportedException{ return super.clone(); } } public String getMethod() { Loading Loading @@ -144,4 +150,52 @@ public class NextcloudRequest implements Serializable { public boolean isFollowRedirects() { return this.followRedirects; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof NextcloudRequest)) { return false; } NextcloudRequest rq = (NextcloudRequest)obj; boolean equal; equal = checkEqual("accountName", this.accountName, rq.accountName); equal &= checkEqual("header", this.header, rq.header); equal &= checkEqual("method", this.method, rq.method); equal &= checkEqual("packageName", this.packageName, rq.packageName); equal &= checkEqual("parameter", this.parameter, rq.parameter); equal &= checkEqual("requestBody", this.requestBody, rq.requestBody); equal &= checkEqual("token", this.token, rq.token); equal &= checkEqual("url", this.url, rq.url); equal &= checkEqual("followRedirects", this.followRedirects, rq.followRedirects); return equal; //return super.equals(obj); } private boolean checkEqual(String name, Object o1, Object o2) { if(o1 == null && o2 == null) { return true; } if(o1 != null) { boolean eq = o1.equals(o2); if(!eq) { System.err.println("[" + name + " ] Expected: " + o1 + " Was: " + o2); } return eq; } else { // o1 == null and o2 != null System.err.println("[" + name + " ] Expected: " + o1 + " Was: " + o2); } return false; } } src/main/java/com/nextcloud/android/sso/api/NextcloudAPI.java +24 −2 Original line number Diff line number Diff line Loading @@ -50,6 +50,9 @@ import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Reader; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.reflect.Type; import java.util.concurrent.atomic.AtomicBoolean; Loading @@ -57,6 +60,8 @@ import io.reactivex.Observable; import io.reactivex.annotations.NonNull; import static com.nextcloud.android.sso.exceptions.SSOException.parseNextcloudCustomException; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; public class NextcloudAPI { Loading @@ -70,7 +75,12 @@ public class NextcloudAPI { private ApiConnectedListener mCallback; private Context mContext; @Documented @Target(METHOD) @Retention(RUNTIME) public @interface FollowRedirects{ } public interface ApiConnectedListener { void onConnected(); Loading @@ -83,8 +93,15 @@ public class NextcloudAPI { this.gson = gson; this.mCallback = callback; new Thread() { public void run() { Log.d(TAG, "run() called " + Thread.currentThread().getName()); connectApiWithBackoff(); } }.start(); //connectApiWithBackoff(); } private String getAccountName() { return mAccount.name; Loading @@ -104,6 +121,7 @@ public class NextcloudAPI { } private void connect() { Log.v(TAG, "Nextcloud Single sign-on connect() called [" + Thread.currentThread().getName() + "]"); if (mDestroyed) { throw new IllegalStateException("API already destroyed! You cannot reuse a stopped API instance"); } Loading Loading @@ -152,7 +170,7 @@ public class NextcloudAPI { */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { Log.i(TAG, "Nextcloud Single sign-on: onServiceConnected"); Log.v(TAG, "Nextcloud Single sign-on: onServiceConnected [" + Thread.currentThread().getName() + "]"); mService = IInputStreamService.Stub.asInterface(service); mBound.set(true); Loading Loading @@ -315,4 +333,8 @@ public class NextcloudAPI { ois.close(); return result; } protected Gson getGson() { return gson; } } src/main/java/com/nextcloud/android/sso/api/NextcloudRetrofitServiceMethod.java +55 −40 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package com.nextcloud.android.sso.api; import android.support.annotation.Nullable; import android.util.Log; import com.google.gson.GsonBuilder; import com.nextcloud.android.sso.aidl.NextcloudRequest; import com.nextcloud.android.sso.helper.Okhttp3Helper; import com.nextcloud.android.sso.helper.Retrofit2Helper; Loading @@ -13,8 +14,10 @@ import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; Loading @@ -25,17 +28,21 @@ import okhttp3.Headers; import okhttp3.MediaType; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.DELETE; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.HEAD; import retrofit2.http.HTTP; import retrofit2.http.Header; import retrofit2.http.Multipart; import retrofit2.http.OPTIONS; import retrofit2.http.PATCH; import retrofit2.http.POST; import retrofit2.http.PUT; import retrofit2.http.Path; import retrofit2.http.Query; import retrofit2.http.Streaming; public class NextcloudRetrofitServiceMethod<T> { Loading @@ -50,69 +57,55 @@ public class NextcloudRetrofitServiceMethod<T> { private static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}"); private static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM); private Method method; String httpMethod; private String httpMethod; private @Nullable String relativeUrl; private @Nullable Headers headers; private @Nullable MediaType contentType; private boolean hasBody; private boolean isFormEncoded; private boolean isMultipart; private NextcloudAPI nextcloudAPI; private Set<String> relativeUrlParamNames; private Type returnType; private boolean followRedirects = false; NextcloudRequest.Builder nextcloudRequest; private final NextcloudRequest.Builder requestBuilder; private final String mApiEndpoint; private Set<String> relativeUrlParamNames; public NextcloudRetrofitServiceMethod(String apiEndpoint, Method method) { this.method = method; this.returnType = method.getGenericReturnType(); /* if(this.returnType instanceof ParameterizedType){ ParameterizedType type = (ParameterizedType) returnType; Type[] typeArguments = type.getActualTypeArguments(); for(Type typeArgument : typeArguments){ Log.d(TAG, "NextcloudRetrofitServiceMethod() " + typeArgument); } } */ this.methodAnnotations = method.getAnnotations(); this.parameterTypes = method.getGenericParameterTypes(); this.parameterAnnotationsArray = method.getParameterAnnotations(); this.mApiEndpoint = apiEndpoint; for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } this.mApiEndpoint = apiEndpoint; if(headers == null) { headers = new Headers.Builder().build(); } nextcloudRequest = new NextcloudRequest.Builder() requestBuilder = new NextcloudRequest.Builder() .setMethod(httpMethod) .setHeader(headers.toMultimap()) .setFollowRedirects(followRedirects) .setUrl(new File(this.mApiEndpoint,relativeUrl).toString()); if(headers != null) { nextcloudRequest.setHeader(headers.toMultimap()); } Log.d(TAG, "NextcloudRetrofitServiceMethod() called with: apiEndpoint = [" + apiEndpoint + "], method = [" + method + "]"); } public T invoke(NextcloudAPI nextcloudAPI, Object[] args) throws Exception { Map<String, String> parameters = new HashMap<>(); NextcloudRequest.Builder rBuilder = (NextcloudRequest.Builder) requestBuilder.clone(); if(parameterAnnotationsArray.length != args.length) { throw new InvalidParameterException("Expected: " + parameterAnnotationsArray.length + " params - were: " + args.length); } Loading @@ -122,15 +115,28 @@ public class NextcloudRetrofitServiceMethod<T> { if(annotation instanceof Query) { parameters.put(((Query)annotation).value(), args[i].toString()); } else if(annotation instanceof Body) { rBuilder.setRequestBody(nextcloudAPI.getGson().toJson(args[i])); } else if(annotation instanceof Path) { String varName = "{" + ((Path)annotation).value() + "}"; String url = rBuilder.build().getUrl(); rBuilder.setUrl(url.replace(varName, args[i].toString())); } else if(annotation instanceof Header) { Map<String, List<String>> headers = rBuilder.build().getHeader(); List<String> arg = new ArrayList<>(); arg.add(args[i].toString()); headers.put(((Header)annotation).value(), arg); rBuilder.setHeader(headers); } else { throw new UnsupportedOperationException("don't know this type yet.. [" + annotation.toString() + "]"); } } NextcloudRequest request = nextcloudRequest NextcloudRequest request = rBuilder .setParameter(parameters) .build(); if(this.returnType instanceof ParameterizedType){ ParameterizedType type = (ParameterizedType) returnType; Type ownerType = type.getRawType(); Loading @@ -151,7 +157,6 @@ public class NextcloudRetrofitServiceMethod<T> { } return nextcloudAPI.performRequest(this.returnType, request); } Loading @@ -163,25 +168,34 @@ public class NextcloudRetrofitServiceMethod<T> { parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false); } else if (annotation instanceof GET) { parseHttpMethodAndPath("GET", ((GET) annotation).value(), false); } else if (annotation instanceof HEAD) { parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false); } else if (annotation instanceof PATCH) { parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true); } else if (annotation instanceof POST) { parseHttpMethodAndPath("POST", ((POST) annotation).value(), true); } else if (annotation instanceof PUT) { parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true); } else if (annotation instanceof OPTIONS) { parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false); } else if (annotation instanceof HTTP) { HTTP http = (HTTP) annotation; parseHttpMethodAndPath(http.method(), http.path(), http.hasBody()); } else if (annotation instanceof Streaming) { Log.v(TAG, "streaming interface"); } else if (annotation instanceof retrofit2.http.Headers) { String[] headersToParse = ((retrofit2.http.Headers) annotation).value(); if (headersToParse.length == 0) { throw methodError(method, "@Headers annotation is empty."); } headers = parseHeaders(headersToParse); } else if(annotation instanceof NextcloudAPI.FollowRedirects) { followRedirects = true; } else { throw new UnsupportedOperationException(annotation.toString()); } /* else if (annotation instanceof HEAD) { parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false); } else if (annotation instanceof PATCH) { parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true); } else if (annotation instanceof OPTIONS) { parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false); } else if (annotation instanceof HTTP) { HTTP http = (HTTP) annotation; parseHttpMethodAndPath(http.method(), http.path(), http.hasBody()); } else if (annotation instanceof Multipart) { if (isFormEncoded) { throw methodError(method, "Only one encoding annotation is allowed."); Loading @@ -193,6 +207,7 @@ public class NextcloudRetrofitServiceMethod<T> { } isFormEncoded = true; } */ } private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) { Loading src/test/java/android/util/Log.java 0 → 100644 +31 −0 Original line number Diff line number Diff line package android.util; // https://stackoverflow.com/questions/36787449/how-to-mock-method-e-in-log public class Log { public static int d(String tag, String msg) { System.out.println("DEBUG: " + tag + ": " + msg); return 0; } public static int i(String tag, String msg) { System.out.println("INFO: " + tag + ": " + msg); return 0; } public static int w(String tag, String msg) { System.out.println("WARN: " + tag + ": " + msg); return 0; } public static int v(String tag, String msg) { System.out.println("VERBOSE: " + tag + ": " + msg); return 0; } public static int e(String tag, String msg) { System.out.println("ERROR: " + tag + ": " + msg); return 0; } // add other methods if required... } Loading
build.gradle +5 −0 Original line number Diff line number Diff line Loading @@ -52,4 +52,9 @@ dependencies { implementation 'com.squareup.retrofit2:retrofit:2.3.0' implementation 'com.squareup.okhttp3:okhttp:3.8.0' // Required for local unit tests (JUnit 4 framework) testImplementation 'junit:junit:4.12' // required if you want to use Mockito for unit tests testImplementation 'org.mockito:mockito-core:2.23.4' }
src/main/java/com/nextcloud/android/sso/aidl/NextcloudRequest.java +55 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.nextcloud.android.sso.aidl; import android.support.annotation.VisibleForTesting; import java.io.Serializable; import java.util.HashMap; import java.util.List; Loading @@ -40,7 +42,7 @@ public class NextcloudRequest implements Serializable { private NextcloudRequest() { } public static class Builder { public static class Builder implements Cloneable { private NextcloudRequest ncr; public Builder() { Loading Loading @@ -95,6 +97,10 @@ public class NextcloudRequest implements Serializable { ncr.followRedirects = followRedirects; return this; } public Object clone() throws CloneNotSupportedException{ return super.clone(); } } public String getMethod() { Loading Loading @@ -144,4 +150,52 @@ public class NextcloudRequest implements Serializable { public boolean isFollowRedirects() { return this.followRedirects; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof NextcloudRequest)) { return false; } NextcloudRequest rq = (NextcloudRequest)obj; boolean equal; equal = checkEqual("accountName", this.accountName, rq.accountName); equal &= checkEqual("header", this.header, rq.header); equal &= checkEqual("method", this.method, rq.method); equal &= checkEqual("packageName", this.packageName, rq.packageName); equal &= checkEqual("parameter", this.parameter, rq.parameter); equal &= checkEqual("requestBody", this.requestBody, rq.requestBody); equal &= checkEqual("token", this.token, rq.token); equal &= checkEqual("url", this.url, rq.url); equal &= checkEqual("followRedirects", this.followRedirects, rq.followRedirects); return equal; //return super.equals(obj); } private boolean checkEqual(String name, Object o1, Object o2) { if(o1 == null && o2 == null) { return true; } if(o1 != null) { boolean eq = o1.equals(o2); if(!eq) { System.err.println("[" + name + " ] Expected: " + o1 + " Was: " + o2); } return eq; } else { // o1 == null and o2 != null System.err.println("[" + name + " ] Expected: " + o1 + " Was: " + o2); } return false; } }
src/main/java/com/nextcloud/android/sso/api/NextcloudAPI.java +24 −2 Original line number Diff line number Diff line Loading @@ -50,6 +50,9 @@ import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Reader; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.reflect.Type; import java.util.concurrent.atomic.AtomicBoolean; Loading @@ -57,6 +60,8 @@ import io.reactivex.Observable; import io.reactivex.annotations.NonNull; import static com.nextcloud.android.sso.exceptions.SSOException.parseNextcloudCustomException; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; public class NextcloudAPI { Loading @@ -70,7 +75,12 @@ public class NextcloudAPI { private ApiConnectedListener mCallback; private Context mContext; @Documented @Target(METHOD) @Retention(RUNTIME) public @interface FollowRedirects{ } public interface ApiConnectedListener { void onConnected(); Loading @@ -83,8 +93,15 @@ public class NextcloudAPI { this.gson = gson; this.mCallback = callback; new Thread() { public void run() { Log.d(TAG, "run() called " + Thread.currentThread().getName()); connectApiWithBackoff(); } }.start(); //connectApiWithBackoff(); } private String getAccountName() { return mAccount.name; Loading @@ -104,6 +121,7 @@ public class NextcloudAPI { } private void connect() { Log.v(TAG, "Nextcloud Single sign-on connect() called [" + Thread.currentThread().getName() + "]"); if (mDestroyed) { throw new IllegalStateException("API already destroyed! You cannot reuse a stopped API instance"); } Loading Loading @@ -152,7 +170,7 @@ public class NextcloudAPI { */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { Log.i(TAG, "Nextcloud Single sign-on: onServiceConnected"); Log.v(TAG, "Nextcloud Single sign-on: onServiceConnected [" + Thread.currentThread().getName() + "]"); mService = IInputStreamService.Stub.asInterface(service); mBound.set(true); Loading Loading @@ -315,4 +333,8 @@ public class NextcloudAPI { ois.close(); return result; } protected Gson getGson() { return gson; } }
src/main/java/com/nextcloud/android/sso/api/NextcloudRetrofitServiceMethod.java +55 −40 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package com.nextcloud.android.sso.api; import android.support.annotation.Nullable; import android.util.Log; import com.google.gson.GsonBuilder; import com.nextcloud.android.sso.aidl.NextcloudRequest; import com.nextcloud.android.sso.helper.Okhttp3Helper; import com.nextcloud.android.sso.helper.Retrofit2Helper; Loading @@ -13,8 +14,10 @@ import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; Loading @@ -25,17 +28,21 @@ import okhttp3.Headers; import okhttp3.MediaType; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.DELETE; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.HEAD; import retrofit2.http.HTTP; import retrofit2.http.Header; import retrofit2.http.Multipart; import retrofit2.http.OPTIONS; import retrofit2.http.PATCH; import retrofit2.http.POST; import retrofit2.http.PUT; import retrofit2.http.Path; import retrofit2.http.Query; import retrofit2.http.Streaming; public class NextcloudRetrofitServiceMethod<T> { Loading @@ -50,69 +57,55 @@ public class NextcloudRetrofitServiceMethod<T> { private static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}"); private static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM); private Method method; String httpMethod; private String httpMethod; private @Nullable String relativeUrl; private @Nullable Headers headers; private @Nullable MediaType contentType; private boolean hasBody; private boolean isFormEncoded; private boolean isMultipart; private NextcloudAPI nextcloudAPI; private Set<String> relativeUrlParamNames; private Type returnType; private boolean followRedirects = false; NextcloudRequest.Builder nextcloudRequest; private final NextcloudRequest.Builder requestBuilder; private final String mApiEndpoint; private Set<String> relativeUrlParamNames; public NextcloudRetrofitServiceMethod(String apiEndpoint, Method method) { this.method = method; this.returnType = method.getGenericReturnType(); /* if(this.returnType instanceof ParameterizedType){ ParameterizedType type = (ParameterizedType) returnType; Type[] typeArguments = type.getActualTypeArguments(); for(Type typeArgument : typeArguments){ Log.d(TAG, "NextcloudRetrofitServiceMethod() " + typeArgument); } } */ this.methodAnnotations = method.getAnnotations(); this.parameterTypes = method.getGenericParameterTypes(); this.parameterAnnotationsArray = method.getParameterAnnotations(); this.mApiEndpoint = apiEndpoint; for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } this.mApiEndpoint = apiEndpoint; if(headers == null) { headers = new Headers.Builder().build(); } nextcloudRequest = new NextcloudRequest.Builder() requestBuilder = new NextcloudRequest.Builder() .setMethod(httpMethod) .setHeader(headers.toMultimap()) .setFollowRedirects(followRedirects) .setUrl(new File(this.mApiEndpoint,relativeUrl).toString()); if(headers != null) { nextcloudRequest.setHeader(headers.toMultimap()); } Log.d(TAG, "NextcloudRetrofitServiceMethod() called with: apiEndpoint = [" + apiEndpoint + "], method = [" + method + "]"); } public T invoke(NextcloudAPI nextcloudAPI, Object[] args) throws Exception { Map<String, String> parameters = new HashMap<>(); NextcloudRequest.Builder rBuilder = (NextcloudRequest.Builder) requestBuilder.clone(); if(parameterAnnotationsArray.length != args.length) { throw new InvalidParameterException("Expected: " + parameterAnnotationsArray.length + " params - were: " + args.length); } Loading @@ -122,15 +115,28 @@ public class NextcloudRetrofitServiceMethod<T> { if(annotation instanceof Query) { parameters.put(((Query)annotation).value(), args[i].toString()); } else if(annotation instanceof Body) { rBuilder.setRequestBody(nextcloudAPI.getGson().toJson(args[i])); } else if(annotation instanceof Path) { String varName = "{" + ((Path)annotation).value() + "}"; String url = rBuilder.build().getUrl(); rBuilder.setUrl(url.replace(varName, args[i].toString())); } else if(annotation instanceof Header) { Map<String, List<String>> headers = rBuilder.build().getHeader(); List<String> arg = new ArrayList<>(); arg.add(args[i].toString()); headers.put(((Header)annotation).value(), arg); rBuilder.setHeader(headers); } else { throw new UnsupportedOperationException("don't know this type yet.. [" + annotation.toString() + "]"); } } NextcloudRequest request = nextcloudRequest NextcloudRequest request = rBuilder .setParameter(parameters) .build(); if(this.returnType instanceof ParameterizedType){ ParameterizedType type = (ParameterizedType) returnType; Type ownerType = type.getRawType(); Loading @@ -151,7 +157,6 @@ public class NextcloudRetrofitServiceMethod<T> { } return nextcloudAPI.performRequest(this.returnType, request); } Loading @@ -163,25 +168,34 @@ public class NextcloudRetrofitServiceMethod<T> { parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false); } else if (annotation instanceof GET) { parseHttpMethodAndPath("GET", ((GET) annotation).value(), false); } else if (annotation instanceof HEAD) { parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false); } else if (annotation instanceof PATCH) { parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true); } else if (annotation instanceof POST) { parseHttpMethodAndPath("POST", ((POST) annotation).value(), true); } else if (annotation instanceof PUT) { parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true); } else if (annotation instanceof OPTIONS) { parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false); } else if (annotation instanceof HTTP) { HTTP http = (HTTP) annotation; parseHttpMethodAndPath(http.method(), http.path(), http.hasBody()); } else if (annotation instanceof Streaming) { Log.v(TAG, "streaming interface"); } else if (annotation instanceof retrofit2.http.Headers) { String[] headersToParse = ((retrofit2.http.Headers) annotation).value(); if (headersToParse.length == 0) { throw methodError(method, "@Headers annotation is empty."); } headers = parseHeaders(headersToParse); } else if(annotation instanceof NextcloudAPI.FollowRedirects) { followRedirects = true; } else { throw new UnsupportedOperationException(annotation.toString()); } /* else if (annotation instanceof HEAD) { parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false); } else if (annotation instanceof PATCH) { parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true); } else if (annotation instanceof OPTIONS) { parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false); } else if (annotation instanceof HTTP) { HTTP http = (HTTP) annotation; parseHttpMethodAndPath(http.method(), http.path(), http.hasBody()); } else if (annotation instanceof Multipart) { if (isFormEncoded) { throw methodError(method, "Only one encoding annotation is allowed."); Loading @@ -193,6 +207,7 @@ public class NextcloudRetrofitServiceMethod<T> { } isFormEncoded = true; } */ } private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) { Loading
src/test/java/android/util/Log.java 0 → 100644 +31 −0 Original line number Diff line number Diff line package android.util; // https://stackoverflow.com/questions/36787449/how-to-mock-method-e-in-log public class Log { public static int d(String tag, String msg) { System.out.println("DEBUG: " + tag + ": " + msg); return 0; } public static int i(String tag, String msg) { System.out.println("INFO: " + tag + ": " + msg); return 0; } public static int w(String tag, String msg) { System.out.println("WARN: " + tag + ": " + msg); return 0; } public static int v(String tag, String msg) { System.out.println("VERBOSE: " + tag + ": " + msg); return 0; } public static int e(String tag, String msg) { System.out.println("ERROR: " + tag + ": " + msg); return 0; } // add other methods if required... }