Skip to content

Commit 56f7b4b

Browse files
authored
Replace Apache Commons by native calls/Guava (#883)
* Replace Commons IO by native calls/Guava * Drop other Apache Commons * Fix tests
1 parent 4a3ebc4 commit 56f7b4b

19 files changed

+56
-76
lines changed

app/build.gradle.kts

+1-5
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,9 @@ dependencies {
184184
implementation(libs.bitfire.vcard4android)
185185

186186
// third-party libs
187-
implementation(libs.commons.collections)
188-
@Suppress("RedundantSuppression")
189-
implementation(libs.commons.io)
190-
implementation(libs.commons.lang)
191-
implementation(libs.commons.text)
192187
@Suppress("RedundantSuppression")
193188
implementation(libs.dnsjava)
189+
implementation(libs.guava)
194190
implementation(libs.mikepenz.aboutLibraries)
195191
implementation(libs.nsk90.kstatemachine)
196192
implementation(libs.okhttp.base)

app/src/androidTest/kotlin/at/bitfire/davdroid/servicedetection/CollectionListRefresherTest.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import okhttp3.mockwebserver.Dispatcher
2424
import okhttp3.mockwebserver.MockResponse
2525
import okhttp3.mockwebserver.MockWebServer
2626
import okhttp3.mockwebserver.RecordedRequest
27-
import org.apache.commons.lang3.StringUtils
2827
import org.junit.After
2928
import org.junit.Assert.assertEquals
3029
import org.junit.Assert.assertFalse
@@ -625,7 +624,7 @@ class CollectionListRefresherTest {
625624
class TestDispatcher: Dispatcher() {
626625

627626
override fun dispatch(request: RecordedRequest): MockResponse {
628-
val path = StringUtils.removeEnd(request.path!!, "/")
627+
val path = request.path!!.trimEnd('/')
629628

630629
if (request.method.equals("PROPFIND", true)) {
631630
val properties = when (path) {

app/src/main/kotlin/at/bitfire/davdroid/sync/CalendarSyncManager.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package at.bitfire.davdroid.sync
77
import android.accounts.Account
88
import android.content.Context
99
import android.content.SyncResult
10+
import android.text.format.Formatter
1011
import at.bitfire.dav4jvm.DavCalendar
1112
import at.bitfire.dav4jvm.MultiResponseCallback
1213
import at.bitfire.dav4jvm.Response
@@ -42,7 +43,6 @@ import okhttp3.HttpUrl
4243
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
4344
import okhttp3.RequestBody
4445
import okhttp3.RequestBody.Companion.toRequestBody
45-
import org.apache.commons.io.FileUtils
4646
import java.io.ByteArrayOutputStream
4747
import java.io.Reader
4848
import java.io.StringReader
@@ -97,7 +97,7 @@ class CalendarSyncManager @AssistedInject constructor(
9797
it.propfind(0, MaxResourceSize.NAME, SupportedReportSet.NAME, GetCTag.NAME, SyncToken.NAME) { response, relation ->
9898
if (relation == Response.HrefRelation.SELF) {
9999
response[MaxResourceSize::class.java]?.maxSize?.let { maxSize ->
100-
Logger.log.info("Calendar accepts events up to ${FileUtils.byteCountToDisplaySize(maxSize)}")
100+
Logger.log.info("Calendar accepts events up to ${Formatter.formatFileSize(context, maxSize)}")
101101
}
102102

103103
response[SupportedReportSet::class.java]?.let { supported ->

app/src/main/kotlin/at/bitfire/davdroid/sync/ContactsSyncManager.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import android.content.ContentResolver
1010
import android.content.Context
1111
import android.content.SyncResult
1212
import android.os.Build
13+
import android.text.format.Formatter
1314
import at.bitfire.dav4jvm.DavAddressBook
1415
import at.bitfire.dav4jvm.MultiResponseCallback
1516
import at.bitfire.dav4jvm.Response
@@ -53,7 +54,6 @@ import okhttp3.MediaType
5354
import okhttp3.Request
5455
import okhttp3.RequestBody
5556
import okhttp3.RequestBody.Companion.toRequestBody
56-
import org.apache.commons.io.FileUtils
5757
import java.io.ByteArrayOutputStream
5858
import java.io.IOException
5959
import java.io.Reader
@@ -168,7 +168,7 @@ class ContactsSyncManager @AssistedInject constructor(
168168
it.propfind(0, MaxResourceSize.NAME, SupportedAddressData.NAME, SupportedReportSet.NAME, GetCTag.NAME, SyncToken.NAME) { response, relation ->
169169
if (relation == Response.HrefRelation.SELF) {
170170
response[MaxResourceSize::class.java]?.maxSize?.let { maxSize ->
171-
Logger.log.info("Address book accepts vCards up to ${FileUtils.byteCountToDisplaySize(maxSize)}")
171+
Logger.log.info("Address book accepts vCards up to ${Formatter.formatFileSize(context, maxSize)}")
172172
}
173173

174174
response[SupportedAddressData::class.java]?.let { supported ->

app/src/main/kotlin/at/bitfire/davdroid/sync/JtxSyncManager.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package at.bitfire.davdroid.sync
77
import android.accounts.Account
88
import android.content.Context
99
import android.content.SyncResult
10+
import android.text.format.Formatter
1011
import at.bitfire.dav4jvm.DavCalendar
1112
import at.bitfire.dav4jvm.MultiResponseCallback
1213
import at.bitfire.dav4jvm.Response
@@ -36,7 +37,6 @@ import okhttp3.HttpUrl
3637
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
3738
import okhttp3.RequestBody
3839
import okhttp3.RequestBody.Companion.toRequestBody
39-
import org.apache.commons.io.FileUtils
4040
import java.io.ByteArrayOutputStream
4141
import java.io.Reader
4242
import java.io.StringReader
@@ -81,7 +81,7 @@ class JtxSyncManager @AssistedInject constructor(
8181
it.propfind(0, GetCTag.NAME, MaxResourceSize.NAME, SyncToken.NAME) { response, relation ->
8282
if (relation == Response.HrefRelation.SELF) {
8383
response[MaxResourceSize::class.java]?.maxSize?.let { maxSize ->
84-
Logger.log.info("Collection accepts resources up to ${FileUtils.byteCountToDisplaySize(maxSize)}")
84+
Logger.log.info("Collection accepts resources up to ${Formatter.formatFileSize(context, maxSize)}")
8585
}
8686

8787
syncState = syncState(response)

app/src/main/kotlin/at/bitfire/davdroid/sync/TasksSyncManager.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package at.bitfire.davdroid.sync
77
import android.accounts.Account
88
import android.content.Context
99
import android.content.SyncResult
10+
import android.text.format.Formatter
1011
import at.bitfire.dav4jvm.DavCalendar
1112
import at.bitfire.dav4jvm.MultiResponseCallback
1213
import at.bitfire.dav4jvm.Response
@@ -36,7 +37,6 @@ import okhttp3.HttpUrl
3637
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
3738
import okhttp3.RequestBody
3839
import okhttp3.RequestBody.Companion.toRequestBody
39-
import org.apache.commons.io.FileUtils
4040
import java.io.ByteArrayOutputStream
4141
import java.io.Reader
4242
import java.io.StringReader
@@ -84,7 +84,7 @@ class TasksSyncManager @AssistedInject constructor(
8484
it.propfind(0, MaxResourceSize.NAME, GetCTag.NAME, SyncToken.NAME) { response, relation ->
8585
if (relation == Response.HrefRelation.SELF) {
8686
response[MaxResourceSize::class.java]?.maxSize?.let { maxSize ->
87-
Logger.log.info("Calendar accepts tasks up to ${FileUtils.byteCountToDisplaySize(maxSize)}")
87+
Logger.log.info("Calendar accepts tasks up to ${Formatter.formatFileSize(context, maxSize)}")
8888
}
8989

9090
syncState = syncState(response)

app/src/main/kotlin/at/bitfire/davdroid/ui/AboutActivity.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ import dagger.hilt.android.AndroidEntryPoint
6565
import dagger.hilt.android.components.ActivityComponent
6666
import kotlinx.coroutines.Dispatchers
6767
import kotlinx.coroutines.launch
68-
import org.apache.commons.io.IOUtils
6968
import org.json.JSONObject
7069
import java.text.Collator
7170
import java.time.LocalDateTime
@@ -207,7 +206,7 @@ class AboutActivity: AppCompatActivity() {
207206
val context = getApplication<Application>()
208207
try {
209208
context.resources.assets.open("translators.json").use { stream ->
210-
val jsonTranslations = JSONObject(IOUtils.toString(stream, Charsets.UTF_8))
209+
val jsonTranslations = JSONObject(stream.readBytes().decodeToString())
211210
val result = LinkedList<Translation>()
212211
for (langCode in jsonTranslations.keys()) {
213212
val jsonTranslators = jsonTranslations.getJSONArray(langCode)

app/src/main/kotlin/at/bitfire/davdroid/ui/DebugInfoActivity.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import at.bitfire.davdroid.BuildConfig
1616
import at.bitfire.davdroid.R
1717
import dagger.hilt.android.AndroidEntryPoint
1818
import okhttp3.HttpUrl
19-
import org.apache.commons.io.FileUtils
2019
import org.apache.commons.lang3.StringUtils
2120
import java.io.File
2221

@@ -129,7 +128,7 @@ class DebugInfoActivity : AppCompatActivity() {
129128
class IntentBuilder(context: Context) {
130129

131130
companion object {
132-
const val MAX_ELEMENT_SIZE = 800 * FileUtils.ONE_KB.toInt()
131+
const val MAX_ELEMENT_SIZE = 800 * 1024 // 800 kB
133132
}
134133

135134
val intent = Intent(context, DebugInfoActivity::class.java)

app/src/main/kotlin/at/bitfire/davdroid/ui/DebugInfoModel.kt

+10-16
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import android.os.StatFs
2424
import android.provider.CalendarContract
2525
import android.provider.ContactsContract
2626
import android.text.format.DateUtils
27+
import android.text.format.Formatter
2728
import androidx.compose.runtime.getValue
2829
import androidx.compose.runtime.mutableStateOf
2930
import androidx.compose.runtime.setValue
@@ -48,20 +49,18 @@ import at.bitfire.davdroid.settings.SettingsManager
4849
import at.bitfire.davdroid.sync.worker.BaseSyncWorker
4950
import at.bitfire.ical4android.TaskProvider
5051
import at.techbee.jtx.JtxContract
52+
import com.google.common.io.ByteStreams
53+
import com.google.common.io.Files
5154
import dagger.assisted.Assisted
5255
import dagger.assisted.AssistedFactory
5356
import dagger.assisted.AssistedInject
5457
import dagger.hilt.android.lifecycle.HiltViewModel
5558
import kotlinx.coroutines.Dispatchers
5659
import kotlinx.coroutines.launch
57-
import org.apache.commons.io.ByteOrderMark
58-
import org.apache.commons.io.FileUtils
59-
import org.apache.commons.io.IOUtils
6060
import org.apache.commons.lang3.exception.ExceptionUtils
6161
import org.dmfs.tasks.contract.TaskContract
6262
import java.io.File
6363
import java.io.IOException
64-
import java.io.StringReader
6564
import java.io.Writer
6665
import java.util.TimeZone
6766
import java.util.logging.Level
@@ -129,8 +128,8 @@ class DebugInfoModel @AssistedInject constructor(
129128
if (details.logs != null) {
130129
val file = File(debugDir, FILE_LOGS)
131130
if (!file.exists() || file.canWrite()) {
132-
file.writer().buffered().use { writer ->
133-
IOUtils.copy(StringReader(details.logs), writer)
131+
file.printWriter().use { writer ->
132+
writer.write(details.logs)
134133
}
135134
uiState = uiState.copy(logFile = file)
136135
} else
@@ -164,7 +163,6 @@ class DebugInfoModel @AssistedInject constructor(
164163
private fun generateDebugInfo(syncAccount: Account?, syncAuthority: String?, cause: Throwable?, localResource: String?, remoteResource: String?) {
165164
val debugInfoFile = File(Logger.debugDir(), FILE_DEBUG_INFO)
166165
debugInfoFile.writer().buffered().use { writer ->
167-
writer.append(ByteOrderMark.UTF_BOM)
168166
writer.append("--- BEGIN DEBUG INFO ---\n\n")
169167

170168
// begin with most specific information
@@ -262,9 +260,9 @@ class DebugInfoModel @AssistedInject constructor(
262260
val filesPath = Environment.getDataDirectory()
263261
val statFs = StatFs(filesPath.path)
264262
writer.append("Internal memory ($filesPath): ")
265-
.append(FileUtils.byteCountToDisplaySize(statFs.availableBytes))
263+
.append(Formatter.formatFileSize(context, statFs.availableBytes))
266264
.append(" free of ")
267-
.append(FileUtils.byteCountToDisplaySize(statFs.totalBytes))
265+
.append(Formatter.formatFileSize(context, statFs.totalBytes))
268266
.append("\n\n")
269267

270268
// power saving
@@ -431,26 +429,22 @@ class DebugInfoModel @AssistedInject constructor(
431429
zip.setLevel(9)
432430
uiState.debugInfo?.let { debugInfo ->
433431
zip.putNextEntry(ZipEntry("debug-info.txt"))
434-
debugInfo.inputStream().use {
435-
IOUtils.copy(it, zip)
436-
}
432+
Files.copy(debugInfo, zip)
437433
zip.closeEntry()
438434
}
439435

440436
val logs = uiState.logFile
441437
if (logs != null) {
442438
// verbose logs available
443439
zip.putNextEntry(ZipEntry(logs.name))
444-
logs.inputStream().use {
445-
IOUtils.copy(it, zip)
446-
}
440+
Files.copy(logs, zip)
447441
zip.closeEntry()
448442
} else {
449443
// logcat (short logs)
450444
try {
451445
Runtime.getRuntime().exec("logcat -d").also { logcat ->
452446
zip.putNextEntry(ZipEntry("logcat.txt"))
453-
IOUtils.copy(logcat.inputStream, zip)
447+
ByteStreams.copy(logcat.inputStream, zip)
454448
}
455449
} catch (e: Exception) {
456450
Logger.log.log(Level.SEVERE, "Couldn't attach logcat", e)

app/src/main/kotlin/at/bitfire/davdroid/ui/intro/BatteryOptimizationsPageContent.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import at.bitfire.davdroid.Constants
3535
import at.bitfire.davdroid.Constants.withStatParams
3636
import at.bitfire.davdroid.R
3737
import at.bitfire.davdroid.ui.AppTheme
38-
import org.apache.commons.text.WordUtils
3938
import java.util.Locale
4039

4140
@Composable
@@ -154,7 +153,7 @@ fun BatteryOptimizationsPageContent(
154153
Text(
155154
text = stringResource(
156155
R.string.intro_autostart_title,
157-
WordUtils.capitalize(Build.MANUFACTURER)
156+
Build.MANUFACTURER.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
158157
),
159158
style = MaterialTheme.typography.labelLarge,
160159
modifier = Modifier.fillMaxWidth()

app/src/main/kotlin/at/bitfire/davdroid/ui/webdav/WebdavMountsScreen.kt

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ package at.bitfire.davdroid.ui.webdav
77
import android.content.Intent
88
import android.net.Uri
99
import android.os.Build
10+
import android.os.FileUtils
1011
import android.provider.DocumentsContract
12+
import android.text.format.Formatter
1113
import androidx.activity.compose.rememberLauncherForActivityResult
1214
import androidx.activity.result.contract.ActivityResultContracts
1315
import androidx.compose.foundation.layout.Arrangement
@@ -71,7 +73,6 @@ import at.bitfire.davdroid.ui.composable.ProgressBar
7173
import at.bitfire.davdroid.ui.widget.ClickableTextWithLink
7274
import at.bitfire.davdroid.util.DavUtils
7375
import okhttp3.HttpUrl
74-
import org.apache.commons.io.FileUtils
7576

7677
@Composable
7778
fun WebdavMountsScreen(
@@ -295,11 +296,12 @@ fun WebdavMountsItem(
295296
.fillMaxWidth()
296297
.padding(vertical = 8.dp),
297298
)
299+
val context = LocalContext.current
298300
Text(
299301
text = stringResource(
300302
R.string.webdav_mounts_quota_used_available,
301-
FileUtils.byteCountToDisplaySize(quotaUsed),
302-
FileUtils.byteCountToDisplaySize(quotaAvailable)
303+
Formatter.formatFileSize(context, quotaUsed),
304+
Formatter.formatFileSize(context, quotaAvailable)
303305
),
304306
modifier = Modifier.fillMaxWidth()
305307
)

app/src/main/kotlin/at/bitfire/davdroid/webdav/RandomAccessCallback.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import android.os.HandlerThread
1212
import android.os.ProxyFileDescriptorCallback
1313
import android.system.ErrnoException
1414
import android.system.OsConstants
15+
import android.text.format.Formatter
1516
import androidx.core.app.NotificationCompat
1617
import androidx.core.app.NotificationManagerCompat
1718
import at.bitfire.dav4jvm.DavResource
@@ -35,7 +36,6 @@ import kotlinx.coroutines.runInterruptible
3536
import okhttp3.Headers
3637
import okhttp3.HttpUrl
3738
import okhttp3.MediaType
38-
import org.apache.commons.io.FileUtils
3939
import ru.nsk.kstatemachine.event.Event
4040
import ru.nsk.kstatemachine.state.State
4141
import ru.nsk.kstatemachine.state.finalState
@@ -76,7 +76,7 @@ class RandomAccessCallback private constructor(
7676
.setCategory(NotificationCompat.CATEGORY_STATUS)
7777
.setContentTitle(context.getString(R.string.webdav_notification_access))
7878
.setContentText(dav.fileName())
79-
.setSubText(FileUtils.byteCountToDisplaySize(fileSize))
79+
.setSubText(Formatter.formatFileSize(context, fileSize))
8080
.setSmallIcon(R.drawable.ic_storage_notify)
8181
.setOngoing(true)
8282
private val notificationTag = url.toString()

app/src/main/kotlin/at/bitfire/davdroid/webdav/StreamingFileDescriptor.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package at.bitfire.davdroid.webdav
77
import android.content.Context
88
import android.os.CancellationSignal
99
import android.os.ParcelFileDescriptor
10+
import android.text.format.Formatter
1011
import androidx.annotation.WorkerThread
1112
import androidx.core.app.NotificationCompat
1213
import androidx.core.app.NotificationManagerCompat
@@ -27,7 +28,6 @@ import okhttp3.MediaType
2728
import okhttp3.RequestBody
2829
import okhttp3.internal.headersContentLength
2930
import okio.BufferedSink
30-
import org.apache.commons.io.FileUtils
3131
import java.io.IOException
3232
import java.util.logging.Level
3333

@@ -45,7 +45,7 @@ class StreamingFileDescriptor(
4545

4646
companion object {
4747
/** 1 MB transfer buffer */
48-
private const val BUFFER_SIZE = FileUtils.ONE_MB.toInt()
48+
private const val BUFFER_SIZE = 1024*1024
4949
}
5050

5151
val dav = DavResource(client.okHttpClient, url)
@@ -123,7 +123,7 @@ class StreamingFileDescriptor(
123123
)
124124
else
125125
// known file size
126-
notification.setSubText(FileUtils.byteCountToDisplaySize(length))
126+
notification.setSubText(Formatter.formatFileSize(context, length))
127127

128128
ParcelFileDescriptor.AutoCloseOutputStream(writeFd).use { output ->
129129
val buffer = ByteArray(BUFFER_SIZE)

app/src/main/kotlin/at/bitfire/davdroid/webdav/cache/DiskCache.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package at.bitfire.davdroid.webdav.cache
66

77
import at.bitfire.davdroid.log.Logger
8-
import org.apache.commons.io.FileUtils
98
import java.io.File
109

1110
/**
@@ -71,7 +70,9 @@ class DiskCache(
7170

7271
@Synchronized
7372
fun clear() {
74-
FileUtils.cleanDirectory(cacheDir)
73+
cacheDir.listFiles()?.forEach { entry ->
74+
entry.delete()
75+
}
7576
}
7677

7778
@Synchronized

0 commit comments

Comments
 (0)