Skip to content

Commit c9a09ac

Browse files
authored
Refactor errors (#422)
1 parent 6941ee9 commit c9a09ac

File tree

251 files changed

+6571
-6405
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

251 files changed

+6571
-6405
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ captures/
4848
.idea/libraries
4949
.idea/jarRepositories.xml
5050
.idea/misc.xml
51+
.idea/migrations.xml
5152
# Android Studio 3 in .gitignore file.
5253
.idea/caches
5354
.idea/modules.xml

readium/adapters/exoplayer/audio/src/main/java/org/readium/adapter/exoplayer/audio/ExoPlayerDataSource.kt

+6-5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import androidx.media3.datasource.TransferListener
1616
import java.io.IOException
1717
import kotlinx.coroutines.runBlocking
1818
import org.readium.r2.shared.publication.Publication
19+
import org.readium.r2.shared.util.data.ReadException
1920
import org.readium.r2.shared.util.getOrThrow
2021
import org.readium.r2.shared.util.resource.Resource
2122
import org.readium.r2.shared.util.resource.buffered
@@ -63,16 +64,15 @@ internal class ExoPlayerDataSource internal constructor(
6364
private var openedResource: OpenedResource? = null
6465

6566
override fun open(dataSpec: DataSpec): Long {
66-
val link = dataSpec.uri.toUrl()
67+
val resource = dataSpec.uri.toUrl()
6768
?.let { publication.linkWithHref(it) }
69+
?.let { publication.get(it) }
70+
// Significantly improves performances, in particular with deflated ZIP entries.
71+
?.buffered(resourceLength = cachedLengths[dataSpec.uri.toString()])
6872
?: throw ExoPlayerDataSourceException.NotFound(
6973
"Can't find a [Link] for URI: ${dataSpec.uri}. Make sure you only request resources declared in the manifest."
7074
)
7175

72-
val resource = publication.get(link)
73-
// Significantly improves performances, in particular with deflated ZIP entries.
74-
.buffered(resourceLength = cachedLengths[dataSpec.uri.toString()])
75-
7676
openedResource = OpenedResource(
7777
resource = resource,
7878
uri = dataSpec.uri,
@@ -117,6 +117,7 @@ internal class ExoPlayerDataSource internal constructor(
117117
val data = runBlocking {
118118
openedResource.resource
119119
.read(range = openedResource.position until (openedResource.position + length))
120+
.mapFailure { ReadException(it) }
120121
.getOrThrow()
121122
}
122123

readium/adapters/exoplayer/audio/src/main/java/org/readium/adapter/exoplayer/audio/ExoPlayerEngineProvider.kt

+5-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi
1818
import org.readium.r2.shared.publication.Locator
1919
import org.readium.r2.shared.publication.Publication
2020
import org.readium.r2.shared.publication.indexOfFirstWithHref
21+
import org.readium.r2.shared.util.Try
2122

2223
/**
2324
* Main component to use the audio navigator with the ExoPlayer adapter.
@@ -38,7 +39,7 @@ public class ExoPlayerEngineProvider(
3839
publication: Publication,
3940
initialLocator: Locator,
4041
initialPreferences: ExoPlayerPreferences
41-
): ExoPlayerEngine {
42+
): Try<ExoPlayerEngine, Nothing> {
4243
val metadataFactory = metadataProvider.createMetadataFactory(publication)
4344
val settingsResolver = ExoPlayerSettingsResolver(defaults)
4445
val dataSourceFactory: DataSource.Factory = ExoPlayerDataSource.Factory(publication)
@@ -56,7 +57,7 @@ public class ExoPlayerEngineProvider(
5657
}
5758
)
5859

59-
return ExoPlayerEngine(
60+
val engine = ExoPlayerEngine(
6061
application = application,
6162
settingsResolver = settingsResolver,
6263
playlist = playlist,
@@ -66,6 +67,8 @@ public class ExoPlayerEngineProvider(
6667
initialPosition = initialPosition,
6768
initialPreferences = initialPreferences
6869
)
70+
71+
return Try.success(engine)
6972
}
7073

7174
override fun createPreferenceEditor(

readium/adapters/pdfium/document/src/main/java/org/readium/adapter/pdfium/document/PdfiumDocument.kt

+17-7
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ import org.readium.r2.shared.InternalReadiumApi
1919
import org.readium.r2.shared.extensions.md5
2020
import org.readium.r2.shared.extensions.tryOrNull
2121
import org.readium.r2.shared.util.Try
22+
import org.readium.r2.shared.util.data.ReadError
23+
import org.readium.r2.shared.util.data.ReadTry
24+
import org.readium.r2.shared.util.flatMap
2225
import org.readium.r2.shared.util.pdf.PdfDocument
2326
import org.readium.r2.shared.util.pdf.PdfDocumentFactory
2427
import org.readium.r2.shared.util.resource.Resource
25-
import org.readium.r2.shared.util.resource.ResourceTry
26-
import org.readium.r2.shared.util.resource.mapCatching
2728
import org.readium.r2.shared.util.use
2829
import timber.log.Timber
2930

@@ -86,25 +87,34 @@ public class PdfiumDocumentFactory(context: Context) : PdfDocumentFactory<Pdfium
8687

8788
private val core by lazy { PdfiumCore(context.applicationContext) }
8889

89-
override suspend fun open(resource: Resource, password: String?): ResourceTry<PdfiumDocument> {
90+
override suspend fun open(resource: Resource, password: String?): ReadTry<PdfiumDocument> {
9091
// First try to open the resource as a file on the FS for performance improvement, as
9192
// PDFium requires the whole PDF document to be loaded in memory when using raw bytes.
9293
return resource.openAsFile(password)
9394
?: resource.openBytes(password)
9495
}
9596

96-
private suspend fun Resource.openAsFile(password: String?): ResourceTry<PdfiumDocument>? =
97+
private suspend fun Resource.openAsFile(password: String?): ReadTry<PdfiumDocument>? =
9798
tryOrNull {
98-
source?.toFile()?.let { file ->
99+
sourceUrl?.toFile()?.let { file ->
99100
withContext(Dispatchers.IO) {
100101
Try.success(core.fromFile(file, password))
101102
}
102103
}
103104
}
104105

105-
private suspend fun Resource.openBytes(password: String?): ResourceTry<PdfiumDocument> =
106+
private suspend fun Resource.openBytes(password: String?): ReadTry<PdfiumDocument> =
106107
use {
107-
read().mapCatching { core.fromBytes(it, password) }
108+
it.read()
109+
.flatMap { bytes ->
110+
try {
111+
Try.success(
112+
core.fromBytes(bytes, password)
113+
)
114+
} catch (e: Exception) {
115+
Try.failure(ReadError.Decoding(e))
116+
}
117+
}
108118
}
109119

110120
private fun PdfiumCore.fromFile(file: File, password: String?): PdfiumDocument =

readium/adapters/pdfium/navigator/src/main/java/org/readium/adapter/pdfium/navigator/PdfiumDocumentFragment.kt

+6-4
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ import org.readium.r2.shared.ExperimentalReadiumApi
2626
import org.readium.r2.shared.publication.Publication
2727
import org.readium.r2.shared.util.SingleJob
2828
import org.readium.r2.shared.util.Url
29+
import org.readium.r2.shared.util.data.ReadError
2930
import org.readium.r2.shared.util.getOrElse
30-
import org.readium.r2.shared.util.resource.Resource
31+
import org.readium.r2.shared.util.toDebugDescription
3132
import timber.log.Timber
3233

3334
@ExperimentalReadiumApi
@@ -40,7 +41,7 @@ public class PdfiumDocumentFragment internal constructor(
4041
) : PdfDocumentFragment<PdfiumSettings>() {
4142

4243
internal interface Listener {
43-
fun onResourceLoadFailed(href: Url, error: Resource.Exception)
44+
fun onResourceLoadFailed(href: Url, error: ReadError)
4445
fun onConfigurePdfView(configurator: PDFView.Configurator)
4546
fun onTap(point: PointF): Boolean
4647
}
@@ -69,12 +70,13 @@ public class PdfiumDocumentFragment internal constructor(
6970
val context = context?.applicationContext ?: return
7071

7172
resetJob.launch {
73+
val resource = requireNotNull(publication.get(href))
7274
val document = PdfiumDocumentFactory(context)
7375
// PDFium crashes when reusing the same PdfDocument, so we must not cache it.
7476
// .cachedIn(publication)
75-
.open(publication.get(href), null)
77+
.open(resource, null)
7678
.getOrElse { error ->
77-
Timber.e(error)
79+
Timber.e(error.toDebugDescription())
7880
listener?.onResourceLoadFailed(href, error)
7981
return@launch
8082
}

readium/adapters/pdfium/navigator/src/main/java/org/readium/adapter/pdfium/navigator/PdfiumEngineProvider.kt

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ package org.readium.adapter.pdfium.navigator
88

99
import android.graphics.PointF
1010
import com.github.barteksc.pdfviewer.PDFView
11-
import org.readium.r2.navigator.OverflowNavigator
12-
import org.readium.r2.navigator.SimplePresentation
11+
import org.readium.r2.navigator.OverflowableNavigator
12+
import org.readium.r2.navigator.SimpleOverflow
1313
import org.readium.r2.navigator.input.TapEvent
1414
import org.readium.r2.navigator.pdf.PdfDocumentFragmentInput
1515
import org.readium.r2.navigator.pdf.PdfEngineProvider
@@ -19,7 +19,7 @@ import org.readium.r2.shared.ExperimentalReadiumApi
1919
import org.readium.r2.shared.publication.Metadata
2020
import org.readium.r2.shared.publication.Publication
2121
import org.readium.r2.shared.util.Url
22-
import org.readium.r2.shared.util.resource.Resource
22+
import org.readium.r2.shared.util.data.ReadError
2323

2424
/**
2525
* Main component to use the PDF navigator with the PDFium adapter.
@@ -49,7 +49,7 @@ public class PdfiumEngineProvider(
4949
initialPageIndex = input.pageIndex,
5050
initialSettings = input.settings,
5151
listener = object : PdfiumDocumentFragment.Listener {
52-
override fun onResourceLoadFailed(href: Url, error: Resource.Exception) {
52+
override fun onResourceLoadFailed(href: Url, error: ReadError) {
5353
input.navigatorListener?.onResourceLoadFailed(href, error)
5454
}
5555

@@ -68,8 +68,8 @@ public class PdfiumEngineProvider(
6868
return settingsPolicy.settings(preferences)
6969
}
7070

71-
override fun computePresentation(settings: PdfiumSettings): OverflowNavigator.Presentation =
72-
SimplePresentation(
71+
override fun computeOverflow(settings: PdfiumSettings): OverflowableNavigator.Overflow =
72+
SimpleOverflow(
7373
readingProgression = settings.readingProgression,
7474
scroll = true,
7575
axis = settings.scrollAxis

readium/adapters/pspdfkit/document/src/main/java/org/readium/adapter/pspdfkit/document/PsPdfKitDocument.kt

+15-14
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,39 @@ import com.pspdfkit.document.PageBinding
1515
import com.pspdfkit.document.PdfDocument as _PsPdfKitDocument
1616
import com.pspdfkit.document.PdfDocumentLoader
1717
import com.pspdfkit.exceptions.InvalidPasswordException
18+
import com.pspdfkit.exceptions.InvalidSignatureException
19+
import java.io.IOException
1820
import kotlin.reflect.KClass
19-
import kotlinx.coroutines.CancellationException
2021
import kotlinx.coroutines.Dispatchers
2122
import kotlinx.coroutines.withContext
2223
import org.readium.r2.shared.publication.ReadingProgression
24+
import org.readium.r2.shared.util.ThrowableError
2325
import org.readium.r2.shared.util.Try
26+
import org.readium.r2.shared.util.data.ReadError
27+
import org.readium.r2.shared.util.data.ReadTry
2428
import org.readium.r2.shared.util.pdf.PdfDocument
2529
import org.readium.r2.shared.util.pdf.PdfDocumentFactory
2630
import org.readium.r2.shared.util.resource.Resource
27-
import org.readium.r2.shared.util.resource.ResourceTry
2831
import timber.log.Timber
2932

3033
public class PsPdfKitDocumentFactory(context: Context) : PdfDocumentFactory<PsPdfKitDocument> {
3134
private val context = context.applicationContext
3235

3336
override val documentType: KClass<PsPdfKitDocument> = PsPdfKitDocument::class
3437

35-
override suspend fun open(resource: Resource, password: String?): ResourceTry<PsPdfKitDocument> =
36-
open(context, DocumentSource(ResourceDataProvider(resource), password))
37-
38-
private suspend fun open(context: Context, documentSource: DocumentSource): ResourceTry<PsPdfKitDocument> =
38+
override suspend fun open(resource: Resource, password: String?): ReadTry<PsPdfKitDocument> =
3939
withContext(Dispatchers.IO) {
40+
val dataProvider = ResourceDataProvider(resource)
41+
val documentSource = DocumentSource(dataProvider, password)
4042
try {
41-
Try.success(
42-
PsPdfKitDocument(PdfDocumentLoader.openDocument(context, documentSource))
43-
)
43+
val innerDocument = PdfDocumentLoader.openDocument(context, documentSource)
44+
Try.success(PsPdfKitDocument(innerDocument))
4445
} catch (e: InvalidPasswordException) {
45-
Try.failure(Resource.Exception.Forbidden(e))
46-
} catch (e: CancellationException) {
47-
throw e
48-
} catch (e: Throwable) {
49-
Try.failure(Resource.Exception.wrap(e))
46+
Try.failure(ReadError.Decoding(ThrowableError(e)))
47+
} catch (e: InvalidSignatureException) {
48+
Try.failure(ReadError.Decoding(ThrowableError(e)))
49+
} catch (e: IOException) {
50+
Try.failure(dataProvider.error!!)
5051
}
5152
}
5253
}

readium/adapters/pspdfkit/document/src/main/java/org/readium/adapter/pspdfkit/document/ResourceDataProvider.kt

+17-8
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,36 @@
77
package org.readium.adapter.pspdfkit.document
88

99
import com.pspdfkit.document.providers.DataProvider
10-
import java.util.*
10+
import java.util.UUID
1111
import kotlinx.coroutines.runBlocking
12+
import org.readium.r2.shared.util.data.ReadError
1213
import org.readium.r2.shared.util.getOrElse
1314
import org.readium.r2.shared.util.isLazyInitialized
1415
import org.readium.r2.shared.util.resource.Resource
1516
import org.readium.r2.shared.util.resource.synchronized
17+
import org.readium.r2.shared.util.toDebugDescription
1618
import timber.log.Timber
1719

1820
internal class ResourceDataProvider(
1921
resource: Resource,
20-
private val onResourceError: (Resource.Exception) -> Unit = { Timber.e(it) }
22+
private val onResourceError: (ReadError) -> Unit = { Timber.e(it.toDebugDescription()) }
2123
) : DataProvider {
2224

25+
var error: ReadError? = null
26+
2327
private val resource =
2428
// PSPDFKit accesses the resource from multiple threads.
2529
resource.synchronized()
2630

27-
private val length: Long = runBlocking {
28-
resource.length()
29-
.getOrElse {
30-
onResourceError(it)
31-
DataProvider.FILE_SIZE_UNKNOWN.toLong()
32-
}
31+
private val length by lazy {
32+
runBlocking {
33+
resource.length()
34+
.getOrElse {
35+
error = it
36+
onResourceError(it)
37+
DataProvider.FILE_SIZE_UNKNOWN.toLong()
38+
}
39+
}
3340
}
3441

3542
override fun getSize(): Long = length
@@ -47,13 +54,15 @@ internal class ResourceDataProvider(
4754
val range = offset until (offset + size)
4855
resource.read(range)
4956
.getOrElse {
57+
error = it
5058
onResourceError(it)
5159
DataProvider.NO_DATA_AVAILABLE
5260
}
5361
}
5462

5563
override fun release() {
5664
if (::resource.isLazyInitialized) {
65+
error = null
5766
runBlocking { resource.close() }
5867
}
5968
}

readium/adapters/pspdfkit/navigator/src/main/java/org/readium/adapter/pspdfkit/navigator/PsPdfKitDocumentFragment.kt

+8-7
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ import org.readium.r2.shared.ExperimentalReadiumApi
5454
import org.readium.r2.shared.publication.Publication
5555
import org.readium.r2.shared.publication.services.isProtected
5656
import org.readium.r2.shared.util.Url
57+
import org.readium.r2.shared.util.data.ReadError
58+
import org.readium.r2.shared.util.data.ReadTry
5759
import org.readium.r2.shared.util.pdf.cachedIn
58-
import org.readium.r2.shared.util.resource.Resource
59-
import org.readium.r2.shared.util.resource.ResourceTry
6060
import timber.log.Timber
6161

6262
@ExperimentalReadiumApi
@@ -69,7 +69,7 @@ public class PsPdfKitDocumentFragment internal constructor(
6969
) : PdfDocumentFragment<PsPdfKitSettings>() {
7070

7171
internal interface Listener {
72-
fun onResourceLoadFailed(href: Url, error: Resource.Exception)
72+
fun onResourceLoadFailed(href: Url, error: ReadError)
7373
fun onConfigurePdfView(builder: PdfConfiguration.Builder): PdfConfiguration.Builder
7474
fun onTap(point: PointF): Boolean
7575
}
@@ -90,13 +90,13 @@ public class PsPdfKitDocumentFragment internal constructor(
9090
private val psPdfKitListener = PsPdfKitListener()
9191

9292
private class DocumentViewModel(
93-
document: suspend () -> ResourceTry<PsPdfKitDocument>
93+
document: suspend () -> ReadTry<PsPdfKitDocument>
9494
) : ViewModel() {
9595

96-
private val _document: Deferred<ResourceTry<PsPdfKitDocument>> =
96+
private val _document: Deferred<ReadTry<PsPdfKitDocument>> =
9797
viewModelScope.async { document() }
9898

99-
suspend fun loadDocument(): ResourceTry<PsPdfKitDocument> =
99+
suspend fun loadDocument(): ReadTry<PsPdfKitDocument> =
100100
_document.await()
101101

102102
@OptIn(ExperimentalCoroutinesApi::class)
@@ -114,9 +114,10 @@ public class PsPdfKitDocumentFragment internal constructor(
114114
createViewModelFactory {
115115
DocumentViewModel(
116116
document = {
117+
val resource = requireNotNull(publication.get(href))
117118
PsPdfKitDocumentFactory(requireContext())
118119
.cachedIn(publication)
119-
.open(publication.get(href), null)
120+
.open(resource, null)
120121
}
121122
)
122123
}

0 commit comments

Comments
 (0)