Setup base Room configuration

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
This commit is contained in:
Álvaro Brey 2022-11-02 22:32:38 +01:00 committed by Tobias Kaminsky (Rebase PR Action)
parent e96390524a
commit d0ab9ff67b
15 changed files with 776 additions and 57 deletions

View file

@ -354,6 +354,10 @@ dependencies {
gplayImplementation "com.google.firebase:firebase-messaging:23.1.0" gplayImplementation "com.google.firebase:firebase-messaging:23.1.0"
implementation 'com.github.nextcloud.android-common:ui:0.3.0' implementation 'com.github.nextcloud.android-common:ui:0.3.0'
implementation "androidx.room:room-runtime:$roomVersion"
kapt "androidx.room:room-compiler:$roomVersion"
} }
configurations.all { configurations.all {
@ -366,7 +370,6 @@ configurations.all {
} }
} }
} }
} }
tasks.withType(Test) { tasks.withType(Test) {

View file

@ -0,0 +1,65 @@
/*
* Nextcloud Android client application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.client.database
import androidx.room.Database
import androidx.room.RoomDatabase
import com.nextcloud.client.database.entity.ArbitraryDataEntity
import com.nextcloud.client.database.entity.CapabilityEntity
import com.nextcloud.client.database.entity.ExternalLinkEntity
import com.nextcloud.client.database.entity.FileEntity
import com.nextcloud.client.database.entity.FilesystemEntity
import com.nextcloud.client.database.entity.ShareEntity
import com.nextcloud.client.database.entity.SyncedFolderEntity
import com.nextcloud.client.database.entity.UploadEntity
import com.nextcloud.client.database.entity.VirtualEntity
import com.owncloud.android.db.ProviderMeta
@Database(
entities = [
ArbitraryDataEntity::class,
CapabilityEntity::class,
ExternalLinkEntity::class,
FileEntity::class,
FilesystemEntity::class,
ShareEntity::class,
SyncedFolderEntity::class,
UploadEntity::class,
VirtualEntity::class
],
version = ProviderMeta.DB_VERSION
)
abstract class NextcloudDatabase : RoomDatabase() {
// companion object {
// val MIGRATION_1_64 = object : Migration(1, 64) {
// override fun migrate(database: SupportSQLiteDatabase) {
// TODO("Not yet implemented, use legacy migrations")
// }
// }
// val MIGRATION_64_65 = object : Migration(64, 65) {
// override fun migrate(database: SupportSQLiteDatabase) {
// // this is just for Room compatibility. No need for any migration
// }
// }
// }
}

View file

@ -0,0 +1,41 @@
/*
* Nextcloud Android client application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.client.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
@Entity(tableName = ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME)
data class ArbitraryDataEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ProviderTableMeta._ID)
val id: Int,
@ColumnInfo(name = ProviderTableMeta.ARBITRARY_DATA_CLOUD_ID)
val cloudId: String?,
@ColumnInfo(name = ProviderTableMeta.ARBITRARY_DATA_KEY)
val key: String?,
@ColumnInfo(name = ProviderTableMeta.ARBITRARY_DATA_VALUE)
val value: String?
)

View file

@ -0,0 +1,129 @@
/*
* Nextcloud Android client application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.client.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
@Entity(tableName = ProviderTableMeta.CAPABILITIES_TABLE_NAME)
data class CapabilityEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ProviderTableMeta._ID)
val id: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME)
val accountName: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_MAYOR)
val versionMajor: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_MINOR)
val versionMinor: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_MICRO)
val versionMicro: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_STRING)
val versionString: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_EDITION)
val versionEditor: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_EXTENDED_SUPPORT)
val extendedSupport: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL)
val corePollinterval: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED)
val sharingApiEnabled: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED)
val sharingPublicEnabled: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED)
val sharingPublicPasswordEnforced: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED)
val sharingPublicExpireDateEnabled: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS)
val sharingPublicExpireDateDays: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED)
val sharingPublicExpireDateEnforced: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL)
val sharingPublicSendMail: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD)
val sharingPublicUpload: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL)
val sharingUserSendMail: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_RESHARING)
val sharingResharing: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING)
val sharingFederationOutgoing: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING)
val sharingFederationIncoming: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING)
val filesBigfilechunking: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_UNDELETE)
val filesUndelete: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_VERSIONING)
val filesVersioning: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_EXTERNAL_LINKS)
val externalLinks: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_NAME)
val serverName: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_COLOR)
val serverColor: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_TEXT_COLOR)
val serverTextColor: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_ELEMENT_COLOR)
val serverElementColor: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN)
val serverSlogan: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_LOGO)
val serverLogo: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_URL)
val serverBackgroundUrl: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION)
val endToEndEncryption: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_ACTIVITY)
val activity: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT)
val serverBackgroundDefault: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_PLAIN)
val serverBackgroundPlain: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT)
val richdocument: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_MIMETYPE_LIST)
val richdocumentMimetypeList: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_DIRECT_EDITING)
val richdocumentDirectEditing: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_TEMPLATES)
val richdocumentTemplates: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_OPTIONAL_MIMETYPE_LIST)
val richdocumentOptionalMimetypeList: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ASK_FOR_OPTIONAL_PASSWORD)
val sharingPublicAskForOptionalPassword: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME)
val richdocumentProductName: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_DIRECT_EDITING_ETAG)
val directEditingEtag: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_USER_STATUS)
val userStatus: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_USER_STATUS_SUPPORTS_EMOJI)
val userStatusSupportsEmoji: Int,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_ETAG)
val etag: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_LOCKING_VERSION)
val filesLockingVersion: String?
)

View file

@ -0,0 +1,47 @@
/*
* Nextcloud Android client application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.client.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
@Entity(tableName = ProviderTableMeta.EXTERNAL_LINKS_TABLE_NAME)
data class ExternalLinkEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ProviderTableMeta._ID)
val id: Int,
@ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_ICON_URL)
val iconUrl: String?,
@ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_LANGUAGE)
val language: String?,
@ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_TYPE)
val type: Int,
@ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_NAME)
val name: String?,
@ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_URL)
val url: String,
@ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_REDIRECT)
val redirect: Int
)

View file

@ -0,0 +1,119 @@
/*
* Nextcloud Android client application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.client.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
@Entity(tableName = ProviderTableMeta.FILE_TABLE_NAME)
data class FileEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ProviderTableMeta._ID)
val id: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_NAME)
val name: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_ENCRYPTED_NAME)
val encryptedName: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_PATH)
val path: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_PATH_DECRYPTED)
val pathDecrypted: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_PARENT)
val parent: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_CREATION)
val creation: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_MODIFIED)
val modified: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_CONTENT_TYPE)
val contentType: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_CONTENT_LENGTH)
val contentLength: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_STORAGE_PATH)
val storagePath: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_ACCOUNT_OWNER)
val accountOwner: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_LAST_SYNC_DATE)
val lastSyncDate: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)
val lastSyncDateForData: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA)
val modifiedAtLastSyncForData: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_ETAG)
val etag: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_ETAG_ON_SERVER)
val etagOnServer: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_SHARED_VIA_LINK)
val sharedViaLink: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_PERMISSIONS)
val permissions: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_REMOTE_ID)
val remoteId: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_UPDATE_THUMBNAIL)
val updateThumbnail: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_IS_DOWNLOADING)
val isDownloading: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_FAVORITE)
val favorite: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_IS_ENCRYPTED)
val isEncrypted: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_ETAG_IN_CONFLICT)
val etagInConflict: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_SHARED_WITH_SHAREE)
val sharedWithSharee: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_MOUNT_TYPE)
val mountType: Int?,
@ColumnInfo(name = ProviderTableMeta.FILE_HAS_PREVIEW)
val hasPreview: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT)
val unreadCommentsCount: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_OWNER_ID)
val ownerId: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_OWNER_DISPLAY_NAME)
val ownerDisplayName: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_NOTE)
val note: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_SHAREES)
val sharees: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_RICH_WORKSPACE)
val richWorkspace: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_METADATA_SIZE)
val metadataSize: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_LOCKED)
val locked: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_LOCK_TYPE)
val lockType: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_LOCK_OWNER)
val lockOwner: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_LOCK_OWNER_DISPLAY_NAME)
val lockOwnerDisplayName: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_LOCK_OWNER_EDITOR)
val lockOwnerEditor: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_LOCK_TIMESTAMP)
val lockTimestamp: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_LOCK_TIMEOUT)
val lockTimeout: Int,
@ColumnInfo(name = ProviderTableMeta.FILE_LOCK_TOKEN)
val lockToken: String?
)

View file

@ -0,0 +1,49 @@
/*
* Nextcloud Android client application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.client.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
@Entity(tableName = ProviderTableMeta.FILESYSTEM_TABLE_NAME)
data class FilesystemEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ProviderTableMeta._ID)
val id: Int,
@ColumnInfo(name = ProviderTableMeta.FILESYSTEM_FILE_LOCAL_PATH)
val localPath: String?,
@ColumnInfo(name = ProviderTableMeta.FILESYSTEM_FILE_IS_FOLDER)
val fileIsFolder: Int,
@ColumnInfo(name = ProviderTableMeta.FILESYSTEM_FILE_FOUND_RECENTLY)
val fileFoundRecently: Long,
@ColumnInfo(name = ProviderTableMeta.FILESYSTEM_FILE_SENT_FOR_UPLOAD)
val fileSentForUpload: Int,
@ColumnInfo(name = ProviderTableMeta.FILESYSTEM_SYNCED_FOLDER_ID)
val syncedFolderId: String?,
@ColumnInfo(name = ProviderTableMeta.FILESYSTEM_CRC32)
val crc32: String?,
@ColumnInfo(name = ProviderTableMeta.FILESYSTEM_FILE_MODIFIED)
val fileModified: Long
)

View file

@ -0,0 +1,73 @@
/*
* Nextcloud Android client application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.client.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
@Entity(tableName = ProviderTableMeta.OCSHARES_TABLE_NAME)
data class ShareEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ProviderTableMeta._ID)
val id: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_FILE_SOURCE)
val fileSource: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_ITEM_SOURCE)
val itemSource: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARE_TYPE)
val shareType: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARE_WITH)
val shareWith: String?,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_PATH)
val path: String?,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_PERMISSIONS)
val permissions: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARED_DATE)
val sharedDate: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_EXPIRATION_DATE)
val expirationDate: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_TOKEN)
val token: String?,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME)
val shareWithDisplayName: String?,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_IS_DIRECTORY)
val isDirectory: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_USER_ID)
val userId: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED)
val idRemoteShared: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER)
val accountOwner: String?,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED)
val isPasswordProtected: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_NOTE)
val note: String?,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_HIDE_DOWNLOAD)
val hideDownload: Int,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARE_LINK)
val shareLink: String?,
@ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARE_LABEL)
val shareLabel: String?
)

View file

@ -0,0 +1,61 @@
/*
* Nextcloud Android client application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.client.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
@Entity(tableName = ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME)
data class SyncedFolderEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ProviderTableMeta._ID)
val id: Int,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_LOCAL_PATH)
val localPath: String?,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_REMOTE_PATH)
val remotePath: String?,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_WIFI_ONLY)
val wifiOnly: Int,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_CHARGING_ONLY)
val chargingOnly: Int,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_EXISTING)
val existing: Int,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_ENABLED)
val enabled: Int,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_ENABLED_TIMESTAMP_MS)
val enabledTimestampMs: Int,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_BY_DATE)
val subfolderByDate: Int,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_ACCOUNT)
val account: String?,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION)
val uploadAction: Int,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_NAME_COLLISION_POLICY)
val nameCollisionPolicy: Int,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_TYPE)
val type: Int,
@ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_HIDDEN)
val hidden: Int
)

View file

@ -0,0 +1,65 @@
/*
* Nextcloud Android client application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.client.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
@Entity(tableName = ProviderTableMeta.UPLOADS_TABLE_NAME)
data class UploadEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ProviderTableMeta._ID)
val id: Int,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_LOCAL_PATH)
val localPath: String?,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_REMOTE_PATH)
val remotePath: String?,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_ACCOUNT_NAME)
val accountName: String?,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_FILE_SIZE)
val fileSize: Long?,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_STATUS)
val status: Int,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_LOCAL_BEHAVIOUR)
val localBehaviour: Int,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_UPLOAD_TIME)
val uploadTime: Int?,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_NAME_COLLISION_POLICY)
val nameCollisionPolicy: Int,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_IS_CREATE_REMOTE_FOLDER)
val isCreateRemoteFolder: Int,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_UPLOAD_END_TIMESTAMP)
val uploadEndTimestamp: Int?,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_LAST_RESULT)
val lastResult: Int?,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_IS_WHILE_CHARGING_ONLY)
val isWhileChargingOnly: Int,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_IS_WIFI_ONLY)
val isWifiOnly: Int,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_CREATED_BY)
val createdBy: Int,
@ColumnInfo(name = ProviderTableMeta.UPLOADS_FOLDER_UNLOCK_TOKEN)
val folderUnlockToken: String?
)

View file

@ -0,0 +1,39 @@
/*
* Nextcloud Android client application
*
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.client.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
@Entity(tableName = ProviderTableMeta.VIRTUAL_TABLE_NAME)
data class VirtualEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ProviderTableMeta._ID)
val id: Int,
@ColumnInfo(name = ProviderTableMeta.VIRTUAL_TYPE)
val type: String,
@ColumnInfo(name = ProviderTableMeta.VIRTUAL_OCFILE_ID)
val ocFileId: Int
)

View file

@ -39,6 +39,7 @@ import com.nextcloud.client.core.AsyncRunner;
import com.nextcloud.client.core.Clock; import com.nextcloud.client.core.Clock;
import com.nextcloud.client.core.ClockImpl; import com.nextcloud.client.core.ClockImpl;
import com.nextcloud.client.core.ThreadPoolAsyncRunner; import com.nextcloud.client.core.ThreadPoolAsyncRunner;
import com.nextcloud.client.database.NextcloudDatabase;
import com.nextcloud.client.device.DeviceInfo; import com.nextcloud.client.device.DeviceInfo;
import com.nextcloud.client.logger.FileLogHandler; import com.nextcloud.client.logger.FileLogHandler;
import com.nextcloud.client.logger.Logger; import com.nextcloud.client.logger.Logger;
@ -57,6 +58,7 @@ import com.owncloud.android.authentication.PassCodeManager;
import com.owncloud.android.datamodel.ArbitraryDataProvider; import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.UploadsStorageManager; import com.owncloud.android.datamodel.UploadsStorageManager;
import com.owncloud.android.db.ProviderMeta;
import com.owncloud.android.ui.activities.data.activities.ActivitiesRepository; import com.owncloud.android.ui.activities.data.activities.ActivitiesRepository;
import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApi; import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApi;
import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApiImpl; import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApiImpl;
@ -75,6 +77,7 @@ import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.room.Room;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
@ -91,6 +94,12 @@ class AppModule {
return application; return application;
} }
@Provides
@Singleton
NextcloudDatabase database(Context context) {
return Room.databaseBuilder(context, NextcloudDatabase.class, ProviderMeta.DB_NAME).build();
}
@Provides @Provides
PackageManager packageManager(Application application) { PackageManager packageManager(Application application) {
return application.getPackageManager(); return application.getPackageManager();

View file

@ -35,7 +35,7 @@ import java.util.List;
*/ */
public class ProviderMeta { public class ProviderMeta {
public static final String DB_NAME = "filelist"; public static final String DB_NAME = "filelist";
public static final int DB_VERSION = 64; public static final int DB_VERSION = 65;
private ProviderMeta() { private ProviderMeta() {
// No instance // No instance

View file

@ -37,12 +37,12 @@ import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri; import android.net.Uri;
import android.os.Binder; import android.os.Binder;
import android.text.TextUtils; import android.text.TextUtils;
import com.nextcloud.client.core.Clock; import com.nextcloud.client.core.Clock;
import com.nextcloud.client.database.NextcloudDatabase;
import com.owncloud.android.MainApp; import com.owncloud.android.MainApp;
import com.owncloud.android.R; import com.owncloud.android.R;
import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.OCFile;
@ -68,6 +68,10 @@ import javax.inject.Inject;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.sqlite.db.SupportSQLiteDatabase;
import androidx.sqlite.db.SupportSQLiteOpenHelper;
import androidx.sqlite.db.SupportSQLiteQuery;
import androidx.sqlite.db.SupportSQLiteQueryBuilder;
import dagger.android.AndroidInjection; import dagger.android.AndroidInjection;
import third_parties.aosp.SQLiteTokenizer; import third_parties.aosp.SQLiteTokenizer;
@ -118,7 +122,7 @@ public class FileContentProvider extends ContentProvider {
private static final Map<String, String> FILE_PROJECTION_MAP; private static final Map<String, String> FILE_PROJECTION_MAP;
static { static {
HashMap<String,String> tempMap = new HashMap<>(); HashMap<String, String> tempMap = new HashMap<>();
for (String projection : ProviderTableMeta.FILE_ALL_COLUMNS) { for (String projection : ProviderTableMeta.FILE_ALL_COLUMNS) {
tempMap.put(projection, projection); tempMap.put(projection, projection);
} }
@ -127,7 +131,8 @@ public class FileContentProvider extends ContentProvider {
@Inject protected Clock clock; @Inject protected Clock clock;
private DataBaseHelper mDbHelper; @Inject NextcloudDatabase database;
private SupportSQLiteOpenHelper mDbHelper;
private Context mContext; private Context mContext;
private UriMatcher mUriMatcher; private UriMatcher mUriMatcher;
@ -138,7 +143,7 @@ public class FileContentProvider extends ContentProvider {
} }
int count; int count;
SQLiteDatabase db = mDbHelper.getWritableDatabase(); SupportSQLiteDatabase db = mDbHelper.getWritableDatabase();
db.beginTransaction(); db.beginTransaction();
try { try {
count = delete(db, uri, where, whereArgs); count = delete(db, uri, where, whereArgs);
@ -150,7 +155,7 @@ public class FileContentProvider extends ContentProvider {
return count; return count;
} }
private int delete(SQLiteDatabase db, Uri uri, String where, String... whereArgs) { private int delete(SupportSQLiteDatabase db, Uri uri, String where, String... whereArgs) {
if (isCallerNotAllowed(uri)) { if (isCallerNotAllowed(uri)) {
return -1; return -1;
} }
@ -205,7 +210,7 @@ public class FileContentProvider extends ContentProvider {
return count; return count;
} }
private int deleteDirectory(SQLiteDatabase db, Uri uri, String where, String... whereArgs) { private int deleteDirectory(SupportSQLiteDatabase db, Uri uri, String where, String... whereArgs) {
int count = 0; int count = 0;
Cursor children = query(uri, PROJECTION_CONTENT_TYPE, null, null, null); Cursor children = query(uri, PROJECTION_CONTENT_TYPE, null, null, null);
@ -238,7 +243,7 @@ public class FileContentProvider extends ContentProvider {
return count; return count;
} }
private int deleteSingleFile(SQLiteDatabase db, Uri uri, String where, String... whereArgs) { private int deleteSingleFile(SupportSQLiteDatabase db, Uri uri, String where, String... whereArgs) {
int count = 0; int count = 0;
try (Cursor c = query(db, uri, PROJECTION_REMOTE_ID, where, whereArgs, null)) { try (Cursor c = query(db, uri, PROJECTION_REMOTE_ID, where, whereArgs, null)) {
@ -255,7 +260,7 @@ public class FileContentProvider extends ContentProvider {
return count; return count;
} }
private int deleteWithUri(SQLiteDatabase db, Uri uri, String where, String[] whereArgs) { private int deleteWithUri(SupportSQLiteDatabase db, Uri uri, String where, String[] whereArgs) {
final String[] argsWithUri = VerificationUtils.prependUriFirstSegmentToSelectionArgs(whereArgs, uri); final String[] argsWithUri = VerificationUtils.prependUriFirstSegmentToSelectionArgs(whereArgs, uri);
return db.delete(ProviderTableMeta.FILE_TABLE_NAME, return db.delete(ProviderTableMeta.FILE_TABLE_NAME,
ProviderTableMeta._ID + "=?" ProviderTableMeta._ID + "=?"
@ -281,7 +286,7 @@ public class FileContentProvider extends ContentProvider {
} }
Uri newUri; Uri newUri;
SQLiteDatabase db = mDbHelper.getWritableDatabase(); SupportSQLiteDatabase db = mDbHelper.getWritableDatabase();
db.beginTransaction(); db.beginTransaction();
try { try {
newUri = insert(db, uri, values); newUri = insert(db, uri, values);
@ -293,7 +298,7 @@ public class FileContentProvider extends ContentProvider {
return newUri; return newUri;
} }
private Uri insert(SQLiteDatabase db, Uri uri, ContentValues values) { private Uri insert(SupportSQLiteDatabase db, Uri uri, ContentValues values) {
// verify only for those requests that are not internal (files table) // verify only for those requests that are not internal (files table)
switch (mUriMatcher.match(uri)) { switch (mUriMatcher.match(uri)) {
case ROOT_DIRECTORY: case ROOT_DIRECTORY:
@ -318,7 +323,7 @@ public class FileContentProvider extends ContentProvider {
// FileDataStorageManager and bring it to FileContentProvider // FileDataStorageManager and bring it to FileContentProvider
if (!doubleCheck.moveToFirst()) { if (!doubleCheck.moveToFirst()) {
doubleCheck.close(); doubleCheck.close();
long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, null, values); long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
if (rowId > 0) { if (rowId > 0) {
return ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId); return ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
} else { } else {
@ -337,7 +342,7 @@ public class FileContentProvider extends ContentProvider {
case SHARES: case SHARES:
Uri insertedShareUri; Uri insertedShareUri;
long idShares = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, null, values); long idShares = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
if (idShares > 0) { if (idShares > 0) {
insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, idShares); insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, idShares);
} else { } else {
@ -350,7 +355,7 @@ public class FileContentProvider extends ContentProvider {
case CAPABILITIES: case CAPABILITIES:
Uri insertedCapUri; Uri insertedCapUri;
long idCapabilities = db.insert(ProviderTableMeta.CAPABILITIES_TABLE_NAME, null, values); long idCapabilities = db.insert(ProviderTableMeta.CAPABILITIES_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
if (idCapabilities > 0) { if (idCapabilities > 0) {
insertedCapUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_CAPABILITIES, idCapabilities); insertedCapUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_CAPABILITIES, idCapabilities);
} else { } else {
@ -360,7 +365,7 @@ public class FileContentProvider extends ContentProvider {
case UPLOADS: case UPLOADS:
Uri insertedUploadUri; Uri insertedUploadUri;
long uploadId = db.insert(ProviderTableMeta.UPLOADS_TABLE_NAME, null, values); long uploadId = db.insert(ProviderTableMeta.UPLOADS_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
if (uploadId > 0) { if (uploadId > 0) {
insertedUploadUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_UPLOADS, uploadId); insertedUploadUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_UPLOADS, uploadId);
} else { } else {
@ -370,7 +375,7 @@ public class FileContentProvider extends ContentProvider {
case SYNCED_FOLDERS: case SYNCED_FOLDERS:
Uri insertedSyncedFolderUri; Uri insertedSyncedFolderUri;
long syncedFolderId = db.insert(ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME, null, values); long syncedFolderId = db.insert(ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
if (syncedFolderId > 0) { if (syncedFolderId > 0) {
insertedSyncedFolderUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS, insertedSyncedFolderUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
syncedFolderId); syncedFolderId);
@ -381,7 +386,7 @@ public class FileContentProvider extends ContentProvider {
case EXTERNAL_LINKS: case EXTERNAL_LINKS:
Uri insertedExternalLinkUri; Uri insertedExternalLinkUri;
long externalLinkId = db.insert(ProviderTableMeta.EXTERNAL_LINKS_TABLE_NAME, null, values); long externalLinkId = db.insert(ProviderTableMeta.EXTERNAL_LINKS_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
if (externalLinkId > 0) { if (externalLinkId > 0) {
insertedExternalLinkUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_EXTERNAL_LINKS, insertedExternalLinkUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_EXTERNAL_LINKS,
externalLinkId); externalLinkId);
@ -392,7 +397,7 @@ public class FileContentProvider extends ContentProvider {
case ARBITRARY_DATA: case ARBITRARY_DATA:
Uri insertedArbitraryDataUri; Uri insertedArbitraryDataUri;
long arbitraryDataId = db.insert(ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME, null, values); long arbitraryDataId = db.insert(ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
if (arbitraryDataId > 0) { if (arbitraryDataId > 0) {
insertedArbitraryDataUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_ARBITRARY_DATA, insertedArbitraryDataUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_ARBITRARY_DATA,
arbitraryDataId); arbitraryDataId);
@ -402,7 +407,7 @@ public class FileContentProvider extends ContentProvider {
return insertedArbitraryDataUri; return insertedArbitraryDataUri;
case VIRTUAL: case VIRTUAL:
Uri insertedVirtualUri; Uri insertedVirtualUri;
long virtualId = db.insert(ProviderTableMeta.VIRTUAL_TABLE_NAME, null, values); long virtualId = db.insert(ProviderTableMeta.VIRTUAL_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
if (virtualId > 0) { if (virtualId > 0) {
insertedVirtualUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_VIRTUAL, virtualId); insertedVirtualUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_VIRTUAL, virtualId);
@ -413,7 +418,7 @@ public class FileContentProvider extends ContentProvider {
return insertedVirtualUri; return insertedVirtualUri;
case FILESYSTEM: case FILESYSTEM:
Uri insertedFilesystemUri; Uri insertedFilesystemUri;
long filesystemId = db.insert(ProviderTableMeta.FILESYSTEM_TABLE_NAME, null, values); long filesystemId = db.insert(ProviderTableMeta.FILESYSTEM_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
if (filesystemId > 0) { if (filesystemId > 0) {
insertedFilesystemUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILESYSTEM, insertedFilesystemUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILESYSTEM,
filesystemId); filesystemId);
@ -426,7 +431,7 @@ public class FileContentProvider extends ContentProvider {
} }
} }
private void updateFilesTableAccordingToShareInsertion(SQLiteDatabase db, ContentValues newShare) { private void updateFilesTableAccordingToShareInsertion(SupportSQLiteDatabase db, ContentValues newShare) {
ContentValues fileValues = new ContentValues(); ContentValues fileValues = new ContentValues();
ShareType newShareType = ShareType.fromValue(newShare.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE)); ShareType newShareType = ShareType.fromValue(newShare.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE));
@ -456,14 +461,14 @@ public class FileContentProvider extends ContentProvider {
newShare.getAsString(ProviderTableMeta.OCSHARES_PATH), newShare.getAsString(ProviderTableMeta.OCSHARES_PATH),
newShare.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER) newShare.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER)
}; };
db.update(ProviderTableMeta.FILE_TABLE_NAME, fileValues, where, whereArgs); db.update(ProviderTableMeta.FILE_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, fileValues, where, whereArgs);
} }
@Override @Override
public boolean onCreate() { public boolean onCreate() {
AndroidInjection.inject(this); AndroidInjection.inject(this);
mDbHelper = new DataBaseHelper(getContext()); mDbHelper = database.getOpenHelper();
mContext = getContext(); mContext = getContext();
if (mContext == null) { if (mContext == null) {
@ -510,7 +515,7 @@ public class FileContentProvider extends ContentProvider {
} }
Cursor result; Cursor result;
SQLiteDatabase db = mDbHelper.getReadableDatabase(); SupportSQLiteDatabase db = mDbHelper.getReadableDatabase();
db.beginTransaction(); db.beginTransaction();
try { try {
result = query(db, uri, projection, selection, selectionArgs, sortOrder); result = query(db, uri, projection, selection, selectionArgs, sortOrder);
@ -521,7 +526,7 @@ public class FileContentProvider extends ContentProvider {
return result; return result;
} }
private Cursor query(SQLiteDatabase db, private Cursor query(SupportSQLiteDatabase db,
Uri uri, Uri uri,
String[] projectionArray, String[] projectionArray,
String selection, String selection,
@ -531,49 +536,49 @@ public class FileContentProvider extends ContentProvider {
// verify only for those requests that are not internal // verify only for those requests that are not internal
final int uriMatch = mUriMatcher.match(uri); final int uriMatch = mUriMatcher.match(uri);
SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder(); String tableName;
switch (uriMatch) { switch (uriMatch) {
case ROOT_DIRECTORY: case ROOT_DIRECTORY:
case DIRECTORY: case DIRECTORY:
case SINGLE_FILE: case SINGLE_FILE:
VerificationUtils.verifyWhere(selection); // prevent injection in public paths VerificationUtils.verifyWhere(selection); // prevent injection in public paths
sqlQuery.setTables(ProviderTableMeta.FILE_TABLE_NAME); tableName = ProviderTableMeta.FILE_TABLE_NAME;
break; break;
case SHARES: case SHARES:
sqlQuery.setTables(ProviderTableMeta.OCSHARES_TABLE_NAME); tableName = ProviderTableMeta.OCSHARES_TABLE_NAME;
break; break;
case CAPABILITIES: case CAPABILITIES:
sqlQuery.setTables(ProviderTableMeta.CAPABILITIES_TABLE_NAME); tableName = ProviderTableMeta.CAPABILITIES_TABLE_NAME;
break; break;
case UPLOADS: case UPLOADS:
sqlQuery.setTables(ProviderTableMeta.UPLOADS_TABLE_NAME); tableName = ProviderTableMeta.UPLOADS_TABLE_NAME;
break; break;
case SYNCED_FOLDERS: case SYNCED_FOLDERS:
sqlQuery.setTables(ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME); tableName = ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME;
break; break;
case EXTERNAL_LINKS: case EXTERNAL_LINKS:
sqlQuery.setTables(ProviderTableMeta.EXTERNAL_LINKS_TABLE_NAME); tableName = ProviderTableMeta.EXTERNAL_LINKS_TABLE_NAME;
break; break;
case ARBITRARY_DATA: case ARBITRARY_DATA:
sqlQuery.setTables(ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME); tableName = ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME;
break; break;
case VIRTUAL: case VIRTUAL:
sqlQuery.setTables(ProviderTableMeta.VIRTUAL_TABLE_NAME); tableName = ProviderTableMeta.VIRTUAL_TABLE_NAME;
break; break;
case FILESYSTEM: case FILESYSTEM:
sqlQuery.setTables(ProviderTableMeta.FILESYSTEM_TABLE_NAME); tableName = ProviderTableMeta.FILESYSTEM_TABLE_NAME;
break; break;
default: default:
throw new IllegalArgumentException("Unknown uri id: " + uri); throw new IllegalArgumentException("Unknown uri id: " + uri);
} }
SupportSQLiteQueryBuilder queryBuilder = SupportSQLiteQueryBuilder.builder(tableName);
// add ID to arguments if Uri has more than one segment // add ID to arguments if Uri has more than one segment
if (uriMatch != ROOT_DIRECTORY && uri.getPathSegments().size() > SINGLE_PATH_SEGMENT ) { if (uriMatch != ROOT_DIRECTORY && uri.getPathSegments().size() > SINGLE_PATH_SEGMENT) {
String idColumn = uriMatch == DIRECTORY ? ProviderTableMeta.FILE_PARENT : ProviderTableMeta._ID; String idColumn = uriMatch == DIRECTORY ? ProviderTableMeta.FILE_PARENT : ProviderTableMeta._ID;
sqlQuery.appendWhere(idColumn + "=?"); selection = idColumn + "=? AND " + selection;
selectionArgs = VerificationUtils.prependUriFirstSegmentToSelectionArgs(selectionArgs, uri); selectionArgs = VerificationUtils.prependUriFirstSegmentToSelectionArgs(selectionArgs, uri);
} }
@ -619,11 +624,12 @@ public class FileContentProvider extends ContentProvider {
// DB case_sensitive // DB case_sensitive
db.execSQL("PRAGMA case_sensitive_like = true"); db.execSQL("PRAGMA case_sensitive_like = true");
// only file list is accessible via content provider, so only this has to be protected with projectionMap // TODO
if ((uriMatch == ROOT_DIRECTORY || uriMatch == SINGLE_FILE || // // only file list is accessible via content provider, so only this has to be protected with projectionMap
uriMatch == DIRECTORY) && projectionArray != null) { // if ((uriMatch == ROOT_DIRECTORY || uriMatch == SINGLE_FILE ||
sqlQuery.setProjectionMap(FILE_PROJECTION_MAP); // uriMatch == DIRECTORY) && projectionArray != null) {
} // sqlQuery.setProjectionMap(FILE_PROJECTION_MAP);
// }
// if both are null, let them pass to query // if both are null, let them pass to query
if (selectionArgs == null && selection != null) { if (selectionArgs == null && selection != null) {
@ -631,8 +637,20 @@ public class FileContentProvider extends ContentProvider {
selection = "(?)"; selection = "(?)";
} }
sqlQuery.setStrict(true); // TODO
Cursor c = sqlQuery.query(db, projectionArray, selection, selectionArgs, null, null, order); // sqlQuery.setStrict(true);
if (!TextUtils.isEmpty(selection)) {
queryBuilder.selection(selection, selectionArgs);
}
if (!TextUtils.isEmpty(order)) {
queryBuilder.orderBy(order);
}
if (projectionArray != null && projectionArray.length > 0) {
queryBuilder.columns(projectionArray);
}
final SupportSQLiteQuery supportSQLiteQuery = queryBuilder.create();
final Cursor c = db.query(supportSQLiteQuery);
c.setNotificationUri(mContext.getContentResolver(), uri); c.setNotificationUri(mContext.getContentResolver(), uri);
return c; return c;
} }
@ -644,7 +662,7 @@ public class FileContentProvider extends ContentProvider {
} }
int count; int count;
SQLiteDatabase db = mDbHelper.getWritableDatabase(); SupportSQLiteDatabase db = mDbHelper.getWritableDatabase();
db.beginTransaction(); db.beginTransaction();
try { try {
count = update(db, uri, values, selection, selectionArgs); count = update(db, uri, values, selection, selectionArgs);
@ -656,7 +674,7 @@ public class FileContentProvider extends ContentProvider {
return count; return count;
} }
private int update(SQLiteDatabase db, Uri uri, ContentValues values, String selection, String... selectionArgs) { private int update(SupportSQLiteDatabase db, Uri uri, ContentValues values, String selection, String... selectionArgs) {
// verify contentValues and selection for public paths to prevent injection // verify contentValues and selection for public paths to prevent injection
switch (mUriMatcher.match(uri)) { switch (mUriMatcher.match(uri)) {
case ROOT_DIRECTORY: case ROOT_DIRECTORY:
@ -670,19 +688,19 @@ public class FileContentProvider extends ContentProvider {
case DIRECTORY: case DIRECTORY:
return 0; return 0;
case SHARES: case SHARES:
return db.update(ProviderTableMeta.OCSHARES_TABLE_NAME, values, selection, selectionArgs); return db.update(ProviderTableMeta.OCSHARES_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
case CAPABILITIES: case CAPABILITIES:
return db.update(ProviderTableMeta.CAPABILITIES_TABLE_NAME, values, selection, selectionArgs); return db.update(ProviderTableMeta.CAPABILITIES_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
case UPLOADS: case UPLOADS:
return db.update(ProviderTableMeta.UPLOADS_TABLE_NAME, values, selection, selectionArgs); return db.update(ProviderTableMeta.UPLOADS_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
case SYNCED_FOLDERS: case SYNCED_FOLDERS:
return db.update(ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME, values, selection, selectionArgs); return db.update(ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
case ARBITRARY_DATA: case ARBITRARY_DATA:
return db.update(ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME, values, selection, selectionArgs); return db.update(ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
case FILESYSTEM: case FILESYSTEM:
return db.update(ProviderTableMeta.FILESYSTEM_TABLE_NAME, values, selection, selectionArgs); return db.update(ProviderTableMeta.FILESYSTEM_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
default: default:
return db.update(ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs); return db.update(ProviderTableMeta.FILE_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
} }
} }
@ -695,7 +713,7 @@ public class FileContentProvider extends ContentProvider {
ContentProviderResult[] results = new ContentProviderResult[operations.size()]; ContentProviderResult[] results = new ContentProviderResult[operations.size()];
int i = 0; int i = 0;
SQLiteDatabase database = mDbHelper.getWritableDatabase(); SupportSQLiteDatabase database = mDbHelper.getWritableDatabase();
database.beginTransaction(); // it's supposed that transactions can be nested database.beginTransaction(); // it's supposed that transactions can be nested
try { try {
for (ContentProviderOperation operation : operations) { for (ContentProviderOperation operation : operations) {

View file

@ -16,6 +16,7 @@ buildscript {
checkerVersion = "3.21.2" checkerVersion = "3.21.2"
exoplayerVersion = "2.18.1" exoplayerVersion = "2.18.1"
documentScannerVersion = "1.0.1" documentScannerVersion = "1.0.1"
roomVersion = "2.4.3"
ciBuild = System.getenv("CI") == "true" ciBuild = System.getenv("CI") == "true"
} }