Loading app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java +4 −3 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ import com.nextcloud.android.sso.model.SingleSignOnAccount; import it.niedermann.owncloud.notes.shared.model.Capabilities; import it.niedermann.owncloud.notes.shared.util.AccountSyncUtil; import it.niedermann.owncloud.notes.shared.util.ResponseUtil; import it.niedermann.owncloud.notes.shared.util.SSOUtil; import trikita.log.Log; Loading @@ -18,7 +19,7 @@ public class CapabilitiesClient { private static final String TAG = CapabilitiesClient.class.getSimpleName(); private static final String HEADER_KEY_ETAG = "ETag"; private static final String HEADER_KEY_ETAG = "etag"; @WorkerThread public static Capabilities getCapabilities(@NonNull Context context, @NonNull SingleSignOnAccount ssoAccount, @Nullable String lastETag, @NonNull ApiProvider apiProvider) throws Throwable { Loading @@ -30,8 +31,8 @@ public class CapabilitiesClient { try { final var response = ocsAPI.getCapabilities(lastETag).blockingSingle(); final var capabilities = response.getResponse().ocs.data; final var headers = response.getHeaders(); if (headers != null) { final var headers = ResponseUtil.getLowerCaseHeaders(response); if (!headers.isEmpty()) { capabilities.setETag(headers.get(HEADER_KEY_ETAG)); } else { Log.w(TAG, "Response headers of capabilities are null"); Loading app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesImportTask.java +28 −1 Original line number Diff line number Diff line package it.niedermann.owncloud.notes.persistence; import static it.niedermann.owncloud.notes.persistence.NotesServerSyncTask.HEADER_KEY_ETAG; import static it.niedermann.owncloud.notes.persistence.NotesServerSyncTask.HEADER_KEY_LAST_MODIFIED; import android.content.Context; import it.niedermann.owncloud.notes.shared.util.ResponseUtil; import trikita.log.Log; import androidx.annotation.NonNull; Loading @@ -10,6 +15,8 @@ import androidx.lifecycle.MutableLiveData; import com.nextcloud.android.sso.AccountImporter; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException; import java.util.Calendar; import java.util.Date; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; Loading Loading @@ -54,7 +61,9 @@ public class NotesImportTask { Log.i(TAG, "… Fetching notes IDs"); final var status = new ImportStatus(); try { final var remoteIds = notesAPI.getNotesIDs().blockingSingle(); final var response = notesAPI.getNotesIDs().blockingSingle(); final var cleanedHeaders = ResponseUtil.getLowerCaseHeaders(response.getKey()); final var remoteIds = response.getValue(); status.total = remoteIds.size(); status$.postValue(status); Log.i(TAG, "… Total count: " + remoteIds.size()); Loading @@ -74,6 +83,24 @@ public class NotesImportTask { } try { latch.await(); // update ETag and Last-Modified in order to reduce size of next response localAccount.setETag(cleanedHeaders.get(HEADER_KEY_ETAG)); final var lastModified = Calendar.getInstance(); lastModified.setTimeInMillis(0); final String lastModifiedHeader = cleanedHeaders.get(HEADER_KEY_LAST_MODIFIED); if (lastModifiedHeader != null) { lastModified.setTimeInMillis(Date.parse(lastModifiedHeader)); } Log.d(TAG, "ETag: " + cleanedHeaders.get(HEADER_KEY_ETAG) + "; Last-Modified: " + lastModified + " (" + lastModified + ")"); localAccount.setModified(lastModified); repo.updateETag(localAccount.getId(), localAccount.getETag()); repo.updateModified(localAccount.getId(), localAccount.getModified().getTimeInMillis()); Log.i(TAG, "IMPORT FINISHED"); callback.onSuccess(null); } catch (InterruptedException e) { Loading app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java +9 −7 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import it.niedermann.owncloud.notes.shared.model.DBStatus; import it.niedermann.owncloud.notes.shared.model.ISyncCallback; import it.niedermann.owncloud.notes.shared.model.SyncResultStatus; import it.niedermann.owncloud.notes.shared.util.ApiVersionUtil; import it.niedermann.owncloud.notes.shared.util.ResponseUtil; import trikita.log.Log; Loading @@ -47,9 +48,9 @@ abstract class NotesServerSyncTask extends Thread { private static final String TAG = NotesServerSyncTask.class.getSimpleName(); private static final String HEADER_KEY_X_NOTES_API_VERSIONS = "X-Notes-API-Versions"; private static final String HEADER_KEY_ETAG = "ETag"; private static final String HEADER_KEY_LAST_MODIFIED = "Last-Modified"; static final String HEADER_KEY_ETAG = "etag"; static final String HEADER_KEY_LAST_MODIFIED = "last-modified"; private static final String HEADER_KEY_X_NOTES_API_VERSIONS = "x-notes-api-versions"; private NotesAPI notesAPI; @NonNull Loading Loading @@ -307,21 +308,22 @@ abstract class NotesServerSyncTask extends Thread { } // update ETag and Last-Modified in order to reduce size of next response localAccount.setETag(fetchResponse.getHeaders().get(HEADER_KEY_ETAG)); final var cleanedHeaders = ResponseUtil.getLowerCaseHeaders(fetchResponse); localAccount.setETag(cleanedHeaders.get(HEADER_KEY_ETAG)); final var lastModified = Calendar.getInstance(); lastModified.setTimeInMillis(0); final String lastModifiedHeader = fetchResponse.getHeaders().get(HEADER_KEY_LAST_MODIFIED); final String lastModifiedHeader = cleanedHeaders.get(HEADER_KEY_LAST_MODIFIED); if (lastModifiedHeader != null) lastModified.setTimeInMillis(Date.parse(lastModifiedHeader)); Log.d(TAG, "ETag: " + fetchResponse.getHeaders().get(HEADER_KEY_ETAG) + "; Last-Modified: " + lastModified + " (" + lastModified + ")"); Log.d(TAG, "ETag: " + cleanedHeaders.get(HEADER_KEY_ETAG) + "; Last-Modified: " + lastModified + " (" + lastModified + ")"); localAccount.setModified(lastModified); repo.updateETag(localAccount.getId(), localAccount.getETag()); repo.updateModified(localAccount.getId(), localAccount.getModified().getTimeInMillis()); final String newApiVersion = ApiVersionUtil.sanitize(fetchResponse.getHeaders().get(HEADER_KEY_X_NOTES_API_VERSIONS)); final String newApiVersion = ApiVersionUtil.sanitize(cleanedHeaders.get(HEADER_KEY_X_NOTES_API_VERSIONS)); localAccount.setApiVersion(newApiVersion); repo.updateApiVersion(localAccount.getId(), newApiVersion); Log.d(TAG, "ApiVersion: " + newApiVersion); Loading app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java +11 −3 Original line number Diff line number Diff line Loading @@ -10,8 +10,10 @@ import com.google.gson.annotations.Expose; import com.nextcloud.android.sso.api.NextcloudAPI; import com.nextcloud.android.sso.api.ParsedResponse; import java.util.AbstractMap; import java.util.Calendar; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import io.reactivex.Observable; Loading Loading @@ -70,11 +72,17 @@ public class NotesAPI { } } public Observable<List<Long>> getNotesIDs() { public Observable<AbstractMap.SimpleEntry<Map<String, String>, List<Long>>> getNotesIDs() { if (ApiVersion.API_VERSION_1_0.equals(usedApiVersion)) { return notesAPI_1_0.getNotesIDs().map(response -> response.getResponse().stream().map(Note::getRemoteId).collect(Collectors.toList())); return notesAPI_1_0.getNotesIDs().map(response -> new AbstractMap.SimpleEntry( response.getHeaders(), response.getResponse().stream().map(Note::getRemoteId).collect(Collectors.toList()) )); } else if (ApiVersion.API_VERSION_0_2.equals(usedApiVersion)) { return notesAPI_0_2.getNotesIDs().map(response -> response.getResponse().stream().map(Note::getRemoteId).collect(Collectors.toList())); return notesAPI_0_2.getNotesIDs().map(response -> new AbstractMap.SimpleEntry( response.getHeaders(), response.getResponse().stream().map(Note::getRemoteId).collect(Collectors.toList()) )); } else { throw new UnsupportedOperationException("Used API version " + usedApiVersion + " does not support getNotesIDs()."); } Loading app/src/main/java/it/niedermann/owncloud/notes/shared/util/ResponseUtil.java 0 → 100644 +31 −0 Original line number Diff line number Diff line package it.niedermann.owncloud.notes.shared.util; import androidx.annotation.NonNull; import com.nextcloud.android.sso.api.ParsedResponse; import java.util.HashMap; import java.util.Map; public class ResponseUtil { /* * Move headers key to lowercase */ @NonNull public static <T> Map<String, String> getLowerCaseHeaders(Map<String, String> headers) { final var cleanedHeaders = new HashMap<String, String>(); if (headers != null) { headers.forEach((k, v) -> cleanedHeaders.put(k.toLowerCase(), v)); } return cleanedHeaders; } /* * Get response headers and move headers key to lowercase */ @NonNull public static <T> Map<String, String> getLowerCaseHeaders(ParsedResponse<T> fetchResponse) { return getLowerCaseHeaders(fetchResponse.getHeaders()); } } Loading
app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java +4 −3 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ import com.nextcloud.android.sso.model.SingleSignOnAccount; import it.niedermann.owncloud.notes.shared.model.Capabilities; import it.niedermann.owncloud.notes.shared.util.AccountSyncUtil; import it.niedermann.owncloud.notes.shared.util.ResponseUtil; import it.niedermann.owncloud.notes.shared.util.SSOUtil; import trikita.log.Log; Loading @@ -18,7 +19,7 @@ public class CapabilitiesClient { private static final String TAG = CapabilitiesClient.class.getSimpleName(); private static final String HEADER_KEY_ETAG = "ETag"; private static final String HEADER_KEY_ETAG = "etag"; @WorkerThread public static Capabilities getCapabilities(@NonNull Context context, @NonNull SingleSignOnAccount ssoAccount, @Nullable String lastETag, @NonNull ApiProvider apiProvider) throws Throwable { Loading @@ -30,8 +31,8 @@ public class CapabilitiesClient { try { final var response = ocsAPI.getCapabilities(lastETag).blockingSingle(); final var capabilities = response.getResponse().ocs.data; final var headers = response.getHeaders(); if (headers != null) { final var headers = ResponseUtil.getLowerCaseHeaders(response); if (!headers.isEmpty()) { capabilities.setETag(headers.get(HEADER_KEY_ETAG)); } else { Log.w(TAG, "Response headers of capabilities are null"); Loading
app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesImportTask.java +28 −1 Original line number Diff line number Diff line package it.niedermann.owncloud.notes.persistence; import static it.niedermann.owncloud.notes.persistence.NotesServerSyncTask.HEADER_KEY_ETAG; import static it.niedermann.owncloud.notes.persistence.NotesServerSyncTask.HEADER_KEY_LAST_MODIFIED; import android.content.Context; import it.niedermann.owncloud.notes.shared.util.ResponseUtil; import trikita.log.Log; import androidx.annotation.NonNull; Loading @@ -10,6 +15,8 @@ import androidx.lifecycle.MutableLiveData; import com.nextcloud.android.sso.AccountImporter; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException; import java.util.Calendar; import java.util.Date; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; Loading Loading @@ -54,7 +61,9 @@ public class NotesImportTask { Log.i(TAG, "… Fetching notes IDs"); final var status = new ImportStatus(); try { final var remoteIds = notesAPI.getNotesIDs().blockingSingle(); final var response = notesAPI.getNotesIDs().blockingSingle(); final var cleanedHeaders = ResponseUtil.getLowerCaseHeaders(response.getKey()); final var remoteIds = response.getValue(); status.total = remoteIds.size(); status$.postValue(status); Log.i(TAG, "… Total count: " + remoteIds.size()); Loading @@ -74,6 +83,24 @@ public class NotesImportTask { } try { latch.await(); // update ETag and Last-Modified in order to reduce size of next response localAccount.setETag(cleanedHeaders.get(HEADER_KEY_ETAG)); final var lastModified = Calendar.getInstance(); lastModified.setTimeInMillis(0); final String lastModifiedHeader = cleanedHeaders.get(HEADER_KEY_LAST_MODIFIED); if (lastModifiedHeader != null) { lastModified.setTimeInMillis(Date.parse(lastModifiedHeader)); } Log.d(TAG, "ETag: " + cleanedHeaders.get(HEADER_KEY_ETAG) + "; Last-Modified: " + lastModified + " (" + lastModified + ")"); localAccount.setModified(lastModified); repo.updateETag(localAccount.getId(), localAccount.getETag()); repo.updateModified(localAccount.getId(), localAccount.getModified().getTimeInMillis()); Log.i(TAG, "IMPORT FINISHED"); callback.onSuccess(null); } catch (InterruptedException e) { Loading
app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java +9 −7 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import it.niedermann.owncloud.notes.shared.model.DBStatus; import it.niedermann.owncloud.notes.shared.model.ISyncCallback; import it.niedermann.owncloud.notes.shared.model.SyncResultStatus; import it.niedermann.owncloud.notes.shared.util.ApiVersionUtil; import it.niedermann.owncloud.notes.shared.util.ResponseUtil; import trikita.log.Log; Loading @@ -47,9 +48,9 @@ abstract class NotesServerSyncTask extends Thread { private static final String TAG = NotesServerSyncTask.class.getSimpleName(); private static final String HEADER_KEY_X_NOTES_API_VERSIONS = "X-Notes-API-Versions"; private static final String HEADER_KEY_ETAG = "ETag"; private static final String HEADER_KEY_LAST_MODIFIED = "Last-Modified"; static final String HEADER_KEY_ETAG = "etag"; static final String HEADER_KEY_LAST_MODIFIED = "last-modified"; private static final String HEADER_KEY_X_NOTES_API_VERSIONS = "x-notes-api-versions"; private NotesAPI notesAPI; @NonNull Loading Loading @@ -307,21 +308,22 @@ abstract class NotesServerSyncTask extends Thread { } // update ETag and Last-Modified in order to reduce size of next response localAccount.setETag(fetchResponse.getHeaders().get(HEADER_KEY_ETAG)); final var cleanedHeaders = ResponseUtil.getLowerCaseHeaders(fetchResponse); localAccount.setETag(cleanedHeaders.get(HEADER_KEY_ETAG)); final var lastModified = Calendar.getInstance(); lastModified.setTimeInMillis(0); final String lastModifiedHeader = fetchResponse.getHeaders().get(HEADER_KEY_LAST_MODIFIED); final String lastModifiedHeader = cleanedHeaders.get(HEADER_KEY_LAST_MODIFIED); if (lastModifiedHeader != null) lastModified.setTimeInMillis(Date.parse(lastModifiedHeader)); Log.d(TAG, "ETag: " + fetchResponse.getHeaders().get(HEADER_KEY_ETAG) + "; Last-Modified: " + lastModified + " (" + lastModified + ")"); Log.d(TAG, "ETag: " + cleanedHeaders.get(HEADER_KEY_ETAG) + "; Last-Modified: " + lastModified + " (" + lastModified + ")"); localAccount.setModified(lastModified); repo.updateETag(localAccount.getId(), localAccount.getETag()); repo.updateModified(localAccount.getId(), localAccount.getModified().getTimeInMillis()); final String newApiVersion = ApiVersionUtil.sanitize(fetchResponse.getHeaders().get(HEADER_KEY_X_NOTES_API_VERSIONS)); final String newApiVersion = ApiVersionUtil.sanitize(cleanedHeaders.get(HEADER_KEY_X_NOTES_API_VERSIONS)); localAccount.setApiVersion(newApiVersion); repo.updateApiVersion(localAccount.getId(), newApiVersion); Log.d(TAG, "ApiVersion: " + newApiVersion); Loading
app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java +11 −3 Original line number Diff line number Diff line Loading @@ -10,8 +10,10 @@ import com.google.gson.annotations.Expose; import com.nextcloud.android.sso.api.NextcloudAPI; import com.nextcloud.android.sso.api.ParsedResponse; import java.util.AbstractMap; import java.util.Calendar; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import io.reactivex.Observable; Loading Loading @@ -70,11 +72,17 @@ public class NotesAPI { } } public Observable<List<Long>> getNotesIDs() { public Observable<AbstractMap.SimpleEntry<Map<String, String>, List<Long>>> getNotesIDs() { if (ApiVersion.API_VERSION_1_0.equals(usedApiVersion)) { return notesAPI_1_0.getNotesIDs().map(response -> response.getResponse().stream().map(Note::getRemoteId).collect(Collectors.toList())); return notesAPI_1_0.getNotesIDs().map(response -> new AbstractMap.SimpleEntry( response.getHeaders(), response.getResponse().stream().map(Note::getRemoteId).collect(Collectors.toList()) )); } else if (ApiVersion.API_VERSION_0_2.equals(usedApiVersion)) { return notesAPI_0_2.getNotesIDs().map(response -> response.getResponse().stream().map(Note::getRemoteId).collect(Collectors.toList())); return notesAPI_0_2.getNotesIDs().map(response -> new AbstractMap.SimpleEntry( response.getHeaders(), response.getResponse().stream().map(Note::getRemoteId).collect(Collectors.toList()) )); } else { throw new UnsupportedOperationException("Used API version " + usedApiVersion + " does not support getNotesIDs()."); } Loading
app/src/main/java/it/niedermann/owncloud/notes/shared/util/ResponseUtil.java 0 → 100644 +31 −0 Original line number Diff line number Diff line package it.niedermann.owncloud.notes.shared.util; import androidx.annotation.NonNull; import com.nextcloud.android.sso.api.ParsedResponse; import java.util.HashMap; import java.util.Map; public class ResponseUtil { /* * Move headers key to lowercase */ @NonNull public static <T> Map<String, String> getLowerCaseHeaders(Map<String, String> headers) { final var cleanedHeaders = new HashMap<String, String>(); if (headers != null) { headers.forEach((k, v) -> cleanedHeaders.put(k.toLowerCase(), v)); } return cleanedHeaders; } /* * Get response headers and move headers key to lowercase */ @NonNull public static <T> Map<String, String> getLowerCaseHeaders(ParsedResponse<T> fetchResponse) { return getLowerCaseHeaders(fetchResponse.getHeaders()); } }