diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java index ca8ffeb62f7b0eb3f56e05f06cdc8685686523bf..b3645e1f3709f050c51b26a1a88d4961da28edf2 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java @@ -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; @@ -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 { @@ -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"); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesImportTask.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesImportTask.java index a33d99c4b7ababd76d4b70f20682ba86785d725c..92fb06594cab793b4257bef066e35e46f6bf2ccc 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesImportTask.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesImportTask.java @@ -1,6 +1,11 @@ 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; @@ -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; @@ -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()); @@ -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) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java index 550aafe9756d8553f885ca92419da68df4ca955e..a66bb6583a2bafe6c488478bc850052fd757e4f9 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java @@ -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; @@ -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 @@ -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); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java index 4eaa81a1974802729063b91c8cb2ec8a528cfe4f..971972be692489310e154acee60a1b9a064f866a 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java @@ -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; @@ -70,11 +72,17 @@ public class NotesAPI { } } - public Observable> getNotesIDs() { + public Observable, List>> 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()."); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/ResponseUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/ResponseUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..fc7ab14351ff5df18843a905e4afc0dd4652cf5e --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/ResponseUtil.java @@ -0,0 +1,31 @@ +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 Map getLowerCaseHeaders(Map headers) { + final var cleanedHeaders = new HashMap(); + + 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 Map getLowerCaseHeaders(ParsedResponse fetchResponse) { + return getLowerCaseHeaders(fetchResponse.getHeaders()); + } +}