From e840fc02a33bb321af45eafe9c6a548e7a1129a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mickae=CC=88l=20Menu?= Date: Tue, 19 Sep 2023 16:00:00 +0200 Subject: [PATCH] Improve error reporting --- .../readium/r2/lcp/LcpContentProtection.kt | 75 ++++++++-------- .../lcp/license/container/LicenseContainer.kt | 2 +- .../readium/r2/shared/asset/AssetRetriever.kt | 74 +++++----------- .../r2/shared/publication/Publication.kt | 88 ++++++++++--------- .../AdeptFallbackContentProtection.kt | 4 +- .../protection/ContentProtection.kt | 4 +- .../LcpFallbackContentProtection.kt | 4 +- .../readium/r2/shared/resource/Factories.kt | 41 ++++----- .../java/org/readium/r2/shared/util/Error.kt | 32 +++++-- .../readium/r2/streamer/ParserAssetFactory.kt | 18 ++-- .../readium/r2/streamer/PublicationFactory.kt | 30 +++---- .../readium/r2/testapp/domain/Bookshelf.kt | 2 +- .../readium/r2/testapp/domain/ImportError.kt | 2 +- .../r2/testapp/domain/PublicationError.kt | 18 ++-- .../r2/testapp/reader/ReaderRepository.kt | 2 +- 15 files changed, 184 insertions(+), 212 deletions(-) diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtection.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtection.kt index ff318d336f..42a18075f8 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtection.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtection.kt @@ -16,14 +16,11 @@ import org.readium.r2.shared.publication.encryption.encryption import org.readium.r2.shared.publication.flatten import org.readium.r2.shared.publication.protection.ContentProtection import org.readium.r2.shared.publication.services.contentProtectionServiceFactory -import org.readium.r2.shared.resource.ArchiveFactory import org.readium.r2.shared.resource.Resource -import org.readium.r2.shared.resource.ResourceFactory import org.readium.r2.shared.resource.TransformingContainer import org.readium.r2.shared.util.AbsoluteUrl import org.readium.r2.shared.util.ThrowableError import org.readium.r2.shared.util.Try -import org.readium.r2.shared.util.Url import org.readium.r2.shared.util.flatMap import org.readium.r2.shared.util.getOrElse @@ -46,7 +43,7 @@ internal class LcpContentProtection( credentials: String?, allowUserInteraction: Boolean, sender: Any? - ): Try { + ): Try { return when (asset) { is Asset.Container -> openPublication(asset, credentials, allowUserInteraction, sender) is Asset.Resource -> openLicense(asset, credentials, allowUserInteraction, sender) @@ -58,7 +55,7 @@ internal class LcpContentProtection( credentials: String?, allowUserInteraction: Boolean, sender: Any? - ): Try { + ): Try { val license = retrieveLicense(asset, credentials, allowUserInteraction, sender) return createResultAsset(asset, license) } @@ -79,7 +76,7 @@ internal class LcpContentProtection( private fun createResultAsset( asset: Asset.Container, license: Try - ): Try { + ): Try { val serviceFactory = LcpContentProtectionService .createFactory(license.getOrNull(), license.failureOrNull()) @@ -110,7 +107,7 @@ internal class LcpContentProtection( credentials: String?, allowUserInteraction: Boolean, sender: Any? - ): Try { + ): Try { val license = retrieveLicense(licenseAsset, credentials, allowUserInteraction, sender) val licenseDoc = license.getOrNull()?.license @@ -120,9 +117,7 @@ internal class LcpContentProtection( LicenseDocument(it) } catch (e: Exception) { return Try.failure( - Publication.OpeningException.ParsingFailed( - ThrowableError(e) - ) + Publication.OpenError.InvalidAsset(cause = ThrowableError(e)) ) } } @@ -135,8 +130,8 @@ internal class LcpContentProtection( val link = checkNotNull(licenseDoc.link(LicenseDocument.Rel.Publication)) val url = (link.url() as? AbsoluteUrl) ?: return Try.failure( - Publication.OpeningException.ParsingFailed( - ThrowableError( + Publication.OpenError.InvalidAsset( + cause = ThrowableError( LcpException.Parsing.Url(rel = LicenseDocument.Rel.Publication.value) ) ) @@ -150,47 +145,47 @@ internal class LcpContentProtection( assetType = AssetType.Archive ) .map { it as Asset.Container } - .mapFailure { Publication.OpeningException.ParsingFailed(it) } + .mapFailure { it.wrap() } } else { (assetRetriever.retrieve(url) as? Asset.Container) ?.let { Try.success(it) } - ?: Try.failure(Publication.OpeningException.ParsingFailed()) + ?: Try.failure(Publication.OpenError.UnsupportedAsset()) } return asset.flatMap { createResultAsset(it, license) } } - private fun ResourceFactory.Error.wrap(): Publication.OpeningException = - when (this) { - is ResourceFactory.Error.NotAResource -> - Publication.OpeningException.NotFound() - is ResourceFactory.Error.Forbidden -> - Publication.OpeningException.Forbidden() - is ResourceFactory.Error.SchemeNotSupported -> - Publication.OpeningException.UnsupportedAsset() - } - - private fun ArchiveFactory.Error.wrap(): Publication.OpeningException = - when (this) { - is ArchiveFactory.Error.FormatNotSupported -> - Publication.OpeningException.UnsupportedAsset() - is ArchiveFactory.Error.PasswordsNotSupported -> - Publication.OpeningException.UnsupportedAsset() - is ArchiveFactory.Error.ResourceReading -> - resourceException.wrap() - } - - private fun Resource.Exception.wrap(): Publication.OpeningException = + private fun Resource.Exception.wrap(): Publication.OpenError = when (this) { is Resource.Exception.Forbidden -> - Publication.OpeningException.Forbidden(ThrowableError(this)) + Publication.OpenError.Forbidden(ThrowableError(this)) is Resource.Exception.NotFound -> - Publication.OpeningException.NotFound(ThrowableError(this)) + Publication.OpenError.NotFound(ThrowableError(this)) Resource.Exception.Offline, is Resource.Exception.Unavailable -> - Publication.OpeningException.Unavailable(ThrowableError(this)) + Publication.OpenError.Unavailable(ThrowableError(this)) is Resource.Exception.Other, is Resource.Exception.BadRequest -> - Publication.OpeningException.Unexpected(this) + Publication.OpenError.Unknown(this) is Resource.Exception.OutOfMemory -> - Publication.OpeningException.OutOfMemory(ThrowableError(this)) + Publication.OpenError.OutOfMemory(ThrowableError(this)) + } + + private fun AssetRetriever.Error.wrap(): Publication.OpenError = + when (this) { + is AssetRetriever.Error.ArchiveFormatNotSupported -> + Publication.OpenError.UnsupportedAsset(this) + is AssetRetriever.Error.Forbidden -> + Publication.OpenError.Forbidden(this) + is AssetRetriever.Error.InvalidAsset -> + Publication.OpenError.InvalidAsset(this) + is AssetRetriever.Error.NotFound -> + Publication.OpenError.NotFound(this) + is AssetRetriever.Error.OutOfMemory -> + Publication.OpenError.OutOfMemory(this) + is AssetRetriever.Error.SchemeNotSupported -> + Publication.OpenError.UnsupportedAsset(this) + is AssetRetriever.Error.Unavailable -> + Publication.OpenError.Unavailable(this) + is AssetRetriever.Error.Unknown -> + Publication.OpenError.Unknown(this) } } diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/license/container/LicenseContainer.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/license/container/LicenseContainer.kt index 8c24322b1c..9b028300a0 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/license/container/LicenseContainer.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/license/container/LicenseContainer.kt @@ -83,7 +83,7 @@ internal fun createLicenseContainer( return when { container.source?.isFile == true -> - FileZipLicenseContainer(container.source!!.path, licensePath) + FileZipLicenseContainer(container.source!!.path!!, licensePath) container.source?.isContent == true -> ContentZipLicenseContainer(context, container, licensePath) else -> diff --git a/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetRetriever.kt b/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetRetriever.kt index 408b693a17..ffa426bfc1 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetRetriever.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/asset/AssetRetriever.kt @@ -23,7 +23,9 @@ import org.readium.r2.shared.resource.Resource import org.readium.r2.shared.resource.ResourceFactory import org.readium.r2.shared.resource.ResourceMediaTypeSnifferContent import org.readium.r2.shared.util.AbsoluteUrl +import org.readium.r2.shared.util.BaseError import org.readium.r2.shared.util.Either +import org.readium.r2.shared.util.Error as SharedError import org.readium.r2.shared.util.ThrowableError import org.readium.r2.shared.util.Try import org.readium.r2.shared.util.Url @@ -59,98 +61,64 @@ public class AssetRetriever( } } - public sealed class Error : org.readium.r2.shared.util.Error { + public sealed class Error(message: String, cause: SharedError?) : BaseError(message, cause) { public class SchemeNotSupported( public val scheme: Url.Scheme, - override val cause: org.readium.r2.shared.util.Error? - ) : Error() { + cause: SharedError? + ) : Error("Scheme $scheme is not supported.", cause) { public constructor(scheme: Url.Scheme, exception: Exception) : this(scheme, ThrowableError(exception)) - - override val message: String = - "Scheme $scheme is not supported." } public class NotFound( public val url: AbsoluteUrl, - override val cause: org.readium.r2.shared.util.Error? - ) : Error() { + cause: SharedError? + ) : Error("Asset could not be found at $url.", cause) { public constructor(url: AbsoluteUrl, exception: Exception) : this(url, ThrowableError(exception)) - - override val message: String = - "Asset could not be found at $url." } - public class InvalidAsset( - override val cause: org.readium.r2.shared.util.Error? - ) : Error() { + public class InvalidAsset(cause: SharedError?) : + Error("Asset looks corrupted.", cause) { public constructor(exception: Exception) : this(ThrowableError(exception)) - - override val message: String = - "Asset looks corrupted." } - public class ArchiveFormatNotSupported( - override val cause: org.readium.r2.shared.util.Error? - ) : Error() { + public class ArchiveFormatNotSupported(cause: SharedError?) : + Error("Archive factory does not support this kind of archive.", cause) { public constructor(exception: Exception) : this(ThrowableError(exception)) - - override val message: String = - "Archive factory does not support this kind of archive." } public class Forbidden( public val url: AbsoluteUrl, - override val cause: org.readium.r2.shared.util.Error - ) : Error() { + cause: SharedError? + ) : Error("Access to asset at url $url is forbidden.", cause) { public constructor(url: AbsoluteUrl, exception: Exception) : this(url, ThrowableError(exception)) - - override val message: String = - "Access to asset at url $url is forbidden." } - public class Unavailable( - override val cause: org.readium.r2.shared.util.Error - ) : Error() { + public class Unavailable(cause: SharedError) : + Error("Asset seems not to be available at the moment.", cause) { public constructor(exception: Exception) : this(ThrowableError(exception)) - - override val message: String = - "Asset seems not to be available at the moment." } - public class OutOfMemory( - error: OutOfMemoryError - ) : Error() { - - override val message: String = - "There is not enough memory on the device to load the asset." - - override val cause: org.readium.r2.shared.util.Error = + public class OutOfMemory(error: OutOfMemoryError) : + Error( + "There is not enough memory on the device to load the asset.", ThrowableError(error) - } - - public class Unknown( - private val exception: Exception - ) : Error() { - - override val message: String = - exception.message ?: "Something unexpected happened." + ) - override val cause: org.readium.r2.shared.util.Error = - ThrowableError(exception) - } + public class Unknown(exception: Exception) : + Error("Something unexpected happened.", ThrowableError(exception)) } /** diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/Publication.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/Publication.kt index 81e25e92ba..6c7bddecd1 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/Publication.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/Publication.kt @@ -32,9 +32,9 @@ import org.readium.r2.shared.resource.EmptyContainer import org.readium.r2.shared.resource.Resource import org.readium.r2.shared.resource.ResourceTry import org.readium.r2.shared.resource.fallback +import org.readium.r2.shared.util.BaseError import org.readium.r2.shared.util.Closeable import org.readium.r2.shared.util.Error -import org.readium.r2.shared.util.MessageError import org.readium.r2.shared.util.ThrowableError import org.readium.r2.shared.util.Url import org.readium.r2.shared.util.mediatype.MediaType @@ -492,78 +492,73 @@ public class Publication( /** * Errors occurring while opening a Publication. */ - public sealed class OpeningException : Error { + public sealed class OpenError(message: String, cause: Error? = null) : + BaseError(message, cause) { /** * The file format could not be recognized by any parser. */ - public class UnsupportedAsset(override val cause: Error? = null) : OpeningException() { - - public constructor(message: String) : this(MessageError(message)) - - override val message: String = - "Asset is not supported." + public class UnsupportedAsset( + message: String, + cause: Error? + ) : OpenError(message, cause) { + public constructor(message: String) : this(message, null) + public constructor(cause: Error? = null) : this("Asset is not supported.", cause) } /** - * The publication file was not found on the file system. + * The publication parsing failed with the given underlying error. */ - public class NotFound(override val cause: Error? = null) : OpeningException() { - - override val message: String = - "Asset couldn't be found." + public class InvalidAsset private constructor( + message: String, + cause: Error? + ) : OpenError(message, cause) { + public constructor(message: String) : this(message, null) + public constructor(cause: Error? = null) : this( + "The asset seems corrupted so the publication cannot be opened.", + cause + ) } /** - * The publication parser failed with the given underlying exception. + * The publication file was not found on the file system. */ - public class ParsingFailed(override val cause: Error? = null) : OpeningException() { - - override val message: String = - "The asset is corrupted so the publication cannot be opened." - } + public class NotFound(cause: Error? = null) : + OpenError("Asset could not be found.", cause) /** * We're not allowed to open the publication at all, for example because it expired. */ - public class Forbidden(override val cause: Error? = null) : OpeningException() { - - override val message: String = - "You are not allowed to open this publication." - } + public class Forbidden(cause: Error? = null) : + OpenError("You are not allowed to open this publication.", cause) /** * The publication can't be opened at the moment, for example because of a networking error. * This error is generally temporary, so the operation may be retried or postponed. */ - public class Unavailable(override val cause: Error? = null) : OpeningException() { - - override val message: String = - "Not available, please try again later." - } + public class Unavailable(cause: Error? = null) : + OpenError("The publication is not available at the moment.", cause) /** * The provided credentials are incorrect and we can't open the publication in a * `restricted` state (e.g. for a password-protected ZIP). */ - public class IncorrectCredentials(override val cause: Error? = null) : OpeningException() { + public class IncorrectCredentials(cause: Error? = null) : + OpenError("Provided credentials were incorrect.", cause) - override val message: String = - "Provided credentials were incorrect." - } - - public class OutOfMemory(override val cause: Error? = null) : OpeningException() { - - override val message: String = - "There is not enough memory available to open device to read the publication." - } + /** + * Opening the publication exceeded the available device memory. + */ + public class OutOfMemory(cause: Error? = null) : + OpenError("There is not enough memory available to open the publication.", cause) - public class Unexpected(override val cause: Error? = null) : OpeningException() { + /** + * An unexpected error occurred. + */ + public class Unknown(cause: Error? = null) : + OpenError("An unexpected error occurred.", cause) { public constructor(exception: Exception) : this(ThrowableError(exception)) - - override val message: String = - "An expected error occurred." } } @@ -697,6 +692,13 @@ public class Publication( ) @Suppress("UNUSED_PARAMETER") public fun contentLayoutForLanguage(language: String?): ReadingProgression = metadata.effectiveReadingProgression + + @Deprecated( + "Renamed to `OpenError`", + replaceWith = ReplaceWith("Publication.OpenError"), + level = DeprecationLevel.ERROR + ) + public sealed class OpeningException } private fun Resource.withMediaType(mediaType: MediaType?): Resource { diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/AdeptFallbackContentProtection.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/AdeptFallbackContentProtection.kt index e49b833161..d1a065d5f8 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/AdeptFallbackContentProtection.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/AdeptFallbackContentProtection.kt @@ -40,10 +40,10 @@ public class AdeptFallbackContentProtection : ContentProtection { credentials: String?, allowUserInteraction: Boolean, sender: Any? - ): Try { + ): Try { if (asset !is Asset.Container) { return Try.failure( - Publication.OpeningException.UnsupportedAsset("A container asset was expected.") + Publication.OpenError.UnsupportedAsset("A container asset was expected.") ) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtection.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtection.kt index 7af2ee8220..005cd33a40 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtection.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/ContentProtection.kt @@ -40,7 +40,7 @@ public interface ContentProtection { /** * Attempts to unlock a potentially protected publication asset. * - * @return A [Asset] in case of success or a [Publication.OpeningException] if the + * @return A [Asset] in case of success or a [Publication.OpenError] if the * asset can't be successfully opened even in restricted mode. */ public suspend fun open( @@ -48,7 +48,7 @@ public interface ContentProtection { credentials: String?, allowUserInteraction: Boolean, sender: Any? - ): Try + ): Try /** * Holds the result of opening an [Asset] with a [ContentProtection]. diff --git a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/LcpFallbackContentProtection.kt b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/LcpFallbackContentProtection.kt index 4caedb63e9..889d6fa3b1 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/LcpFallbackContentProtection.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/publication/protection/LcpFallbackContentProtection.kt @@ -47,10 +47,10 @@ public class LcpFallbackContentProtection( credentials: String?, allowUserInteraction: Boolean, sender: Any? - ): Try { + ): Try { if (asset !is Asset.Container) { return Try.failure( - Publication.OpeningException.UnsupportedAsset("A container asset was expected.") + Publication.OpenError.UnsupportedAsset("A container asset was expected.") ) } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/resource/Factories.kt b/readium/shared/src/main/java/org/readium/r2/shared/resource/Factories.kt index 1f0a2e5d2e..2229e31638 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/resource/Factories.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/resource/Factories.kt @@ -7,6 +7,8 @@ package org.readium.r2.shared.resource import org.readium.r2.shared.util.AbsoluteUrl +import org.readium.r2.shared.util.BaseError +import org.readium.r2.shared.util.Error as SharedError import org.readium.r2.shared.util.ThrowableError import org.readium.r2.shared.util.Try import org.readium.r2.shared.util.Url @@ -20,11 +22,11 @@ import org.readium.r2.shared.util.tryRecover */ public fun interface ResourceFactory { - public sealed class Error : org.readium.r2.shared.util.Error { + public sealed class Error : SharedError { public class SchemeNotSupported( public val scheme: Url.Scheme, - override val cause: org.readium.r2.shared.util.Error? = null + override val cause: SharedError? = null ) : Error() { public constructor(scheme: Url.Scheme, exception: Exception) : this( @@ -38,7 +40,7 @@ public fun interface ResourceFactory { public class NotAResource( public val url: AbsoluteUrl, - override val cause: org.readium.r2.shared.util.Error? = null + override val cause: SharedError? = null ) : Error() { public constructor(url: AbsoluteUrl, exception: Exception) : this( @@ -51,7 +53,7 @@ public fun interface ResourceFactory { } public class Forbidden( - override val cause: org.readium.r2.shared.util.Error + override val cause: SharedError ) : Error() { public constructor(exception: Exception) : this(ThrowableError(exception)) @@ -72,11 +74,11 @@ public fun interface ResourceFactory { */ public fun interface ContainerFactory { - public sealed class Error : org.readium.r2.shared.util.Error { + public sealed class Error : SharedError { public class SchemeNotSupported( public val scheme: Url.Scheme, - override val cause: org.readium.r2.shared.util.Error? = null + override val cause: SharedError? = null ) : Error() { public constructor(scheme: Url.Scheme, exception: Exception) : this( @@ -90,7 +92,7 @@ public fun interface ContainerFactory { public class NotAContainer( public val url: Url, - override val cause: org.readium.r2.shared.util.Error? = null + override val cause: SharedError? = null ) : Error() { public constructor(url: Url, exception: Exception) : this( @@ -103,7 +105,7 @@ public fun interface ContainerFactory { } public class Forbidden( - override val cause: org.readium.r2.shared.util.Error + override val cause: SharedError ) : Error() { public constructor(exception: Exception) : this(ThrowableError(exception)) @@ -123,40 +125,31 @@ public fun interface ContainerFactory { */ public fun interface ArchiveFactory { - public sealed class Error : org.readium.r2.shared.util.Error { + public sealed class Error(message: String, cause: SharedError?) : BaseError(message, cause) { public class FormatNotSupported( - override val cause: org.readium.r2.shared.util.Error? = null - ) : Error() { + cause: SharedError? = null + ) : Error("Archive format not supported.", cause) { public constructor(exception: Exception) : this(ThrowableError(exception)) - - override val message: String = - "Archive format not supported." } public class PasswordsNotSupported( - override val cause: org.readium.r2.shared.util.Error? = null - ) : Error() { + cause: SharedError? = null + ) : Error("Password feature is not supported.", cause) { public constructor(exception: Exception) : this(ThrowableError(exception)) - - override val message: String = - "Password feature is not supported." } public class ResourceReading( - override val cause: org.readium.r2.shared.util.Error?, + cause: SharedError?, public val resourceException: Resource.Exception - ) : Error() { + ) : Error("An error occurred while attempting to read the resource.", cause) { public constructor(exception: Resource.Exception) : this( ThrowableError(exception), exception ) - - override val message: String = - "An error occurred while attempting to read the resource." } } diff --git a/readium/shared/src/main/java/org/readium/r2/shared/util/Error.kt b/readium/shared/src/main/java/org/readium/r2/shared/util/Error.kt index 3b9a430764..ce365cd1fb 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/util/Error.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/util/Error.kt @@ -29,21 +29,35 @@ public interface Error { */ public class ThrowableError( public val throwable: Throwable -) : Error { - - override val message: String = - throwable.message ?: "Exception" - - override val cause: Error? = - null -} +) : BaseError(throwable.message ?: throwable.toString(), cause = null) /** * A basic [Error] implementation with a message. */ public class MessageError( override val message: String -) : Error { +) : BaseError(message, cause = null) +/** + * A basic implementation of [Error] able to print itself in a structured way. + */ +public abstract class BaseError( + override val message: String, override val cause: Error? = null +) : Error { + override fun toString(): String { + var desc = "${javaClass.nameWithEnclosingClasses()}: $message" + if (cause != null) { + desc += "\n ${cause.toString().prependIndent(" ")}" + } + return desc + } + + private fun Class<*>.nameWithEnclosingClasses(): String { + var name = simpleName + enclosingClass?.let { + name = "${it.nameWithEnclosingClasses()}.$name" + } + return name + } } diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/ParserAssetFactory.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/ParserAssetFactory.kt index c968304e43..30f5deff30 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/ParserAssetFactory.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/ParserAssetFactory.kt @@ -37,7 +37,7 @@ internal class ParserAssetFactory( suspend fun createParserAsset( asset: Asset - ): Try { + ): Try { return when (asset) { is Asset.Container -> createParserAssetForContainer(asset) @@ -48,7 +48,7 @@ internal class ParserAssetFactory( private fun createParserAssetForContainer( asset: Asset.Container - ): Try = + ): Try = Try.success( PublicationParser.Asset( mediaType = asset.mediaType, @@ -58,7 +58,7 @@ internal class ParserAssetFactory( private suspend fun createParserAssetForResource( asset: Asset.Resource - ): Try = + ): Try = if (asset.mediaType.isRwpm) { createParserAssetForManifest(asset) } else { @@ -67,22 +67,22 @@ internal class ParserAssetFactory( private suspend fun createParserAssetForManifest( asset: Asset.Resource - ): Try { + ): Try { val manifest = asset.resource.readAsRwpm() - .mapFailure { Publication.OpeningException.ParsingFailed(ThrowableError(it)) } + .mapFailure { Publication.OpenError.InvalidAsset(ThrowableError(it)) } .getOrElse { return Try.failure(it) } val baseUrl = manifest.linkWithRel("self")?.href?.resolve() ?: return Try.failure( - Publication.OpeningException.ParsingFailed( + Publication.OpenError.InvalidAsset( MessageError("No self link in the manifest.") ) ) if (baseUrl !is AbsoluteUrl) { return Try.failure( - Publication.OpeningException.ParsingFailed( + Publication.OpenError.InvalidAsset( MessageError("Self link is not absolute.") ) ) @@ -90,7 +90,7 @@ internal class ParserAssetFactory( if (!baseUrl.isHttp) { return Try.failure( - Publication.OpeningException.UnsupportedAsset( + Publication.OpenError.UnsupportedAsset( "Self link doesn't use the HTTP(S) scheme." ) ) @@ -115,7 +115,7 @@ internal class ParserAssetFactory( private fun createParserAssetForContent( asset: Asset.Resource - ): Try { + ): Try { // Historically, the reading order of a standalone file contained a single link with the // HREF "/$assetName". This was fragile if the asset named changed, or was different on // other devices. To avoid this, we now use a single link with the HREF diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/PublicationFactory.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/PublicationFactory.kt index 38b1375563..7d7a09ed19 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/PublicationFactory.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/PublicationFactory.kt @@ -29,7 +29,7 @@ import org.readium.r2.streamer.parser.image.ImageParser import org.readium.r2.streamer.parser.pdf.PdfParser import org.readium.r2.streamer.parser.readium.ReadiumWebPubParser -internal typealias PublicationTry = Try +internal typealias PublicationTry = Try /** * Opens a Publication using a list of parsers. @@ -131,7 +131,7 @@ public class PublicationFactory( * It can be used to modify the manifest, the root container or the list of service * factories of the [Publication]. * @param warnings Logger used to broadcast non-fatal parsing warnings. - * @return A [Publication] or a [Publication.OpeningException] in case of failure. + * @return A [Publication] or a [Publication.OpenError] in case of failure. */ public suspend fun open( asset: Asset, @@ -170,7 +170,7 @@ public class PublicationFactory( asset: Asset, onCreatePublication: Publication.Builder.() -> Unit, warnings: WarningLogger? - ): Try { + ): Try { val parserAsset = parserAssetFactory.createParserAsset(asset) .getOrElse { return Try.failure(it) } return openParserAsset(parserAsset, onCreatePublication, warnings) @@ -184,11 +184,11 @@ public class PublicationFactory( sender: Any?, onCreatePublication: Publication.Builder.() -> Unit, warnings: WarningLogger? - ): Try { + ): Try { val protectedAsset = contentProtections[contentProtectionScheme] ?.open(asset, credentials, allowUserInteraction, sender) ?.getOrElse { return Try.failure(it) } - ?: return Try.failure(Publication.OpeningException.Forbidden()) + ?: return Try.failure(Publication.OpenError.Forbidden()) val parserAsset = PublicationParser.Asset( protectedAsset.mediaType, @@ -207,7 +207,7 @@ public class PublicationFactory( publicationAsset: PublicationParser.Asset, onCreatePublication: Publication.Builder.() -> Unit = {}, warnings: WarningLogger? = null - ): Try { + ): Try { val builder = parse(publicationAsset, warnings) .getOrElse { return Try.failure(wrapParserException(it)) } @@ -233,26 +233,26 @@ public class PublicationFactory( return Try.failure(PublicationParser.Error.FormatNotSupported()) } - private fun wrapParserException(e: PublicationParser.Error): Publication.OpeningException = + private fun wrapParserException(e: PublicationParser.Error): Publication.OpenError = when (e) { is PublicationParser.Error.FormatNotSupported -> - Publication.OpeningException.UnsupportedAsset("Cannot find a parser for this asset") + Publication.OpenError.UnsupportedAsset("Cannot find a parser for this asset") is PublicationParser.Error.IO -> when (e.resourceError) { is Resource.Exception.BadRequest, is Resource.Exception.Other -> - Publication.OpeningException.Unexpected(e) + Publication.OpenError.Unknown(e) is Resource.Exception.Forbidden -> - Publication.OpeningException.Forbidden(e) + Publication.OpenError.Forbidden(e) is Resource.Exception.NotFound -> - Publication.OpeningException.ParsingFailed(e) + Publication.OpenError.InvalidAsset(e) is Resource.Exception.OutOfMemory -> - Publication.OpeningException.OutOfMemory(e) + Publication.OpenError.OutOfMemory(e) is Resource.Exception.Unavailable, is Resource.Exception.Offline -> - Publication.OpeningException.Unavailable(e) + Publication.OpenError.Unavailable(e) } is PublicationParser.Error.OutOfMemory -> - Publication.OpeningException.OutOfMemory(e) + Publication.OpenError.OutOfMemory(e) is PublicationParser.Error.ParsingFailed -> - Publication.OpeningException.ParsingFailed(e) + Publication.OpenError.InvalidAsset(e) } } diff --git a/test-app/src/main/java/org/readium/r2/testapp/domain/Bookshelf.kt b/test-app/src/main/java/org/readium/r2/testapp/domain/Bookshelf.kt index 5e933668c3..480775f0be 100644 --- a/test-app/src/main/java/org/readium/r2/testapp/domain/Bookshelf.kt +++ b/test-app/src/main/java/org/readium/r2/testapp/domain/Bookshelf.kt @@ -156,7 +156,7 @@ class Bookshelf( } } .onFailure { - Timber.d("Cannot open publication: $it.") + Timber.e("Cannot open publication: $it.") return Try.failure( ImportError.PublicationError(PublicationError(it)) ) diff --git a/test-app/src/main/java/org/readium/r2/testapp/domain/ImportError.kt b/test-app/src/main/java/org/readium/r2/testapp/domain/ImportError.kt index 137eafe7a7..4ce6487b87 100644 --- a/test-app/src/main/java/org/readium/r2/testapp/domain/ImportError.kt +++ b/test-app/src/main/java/org/readium/r2/testapp/domain/ImportError.kt @@ -34,7 +34,7 @@ sealed class ImportError( companion object { operator fun invoke( - error: Publication.OpeningException + error: Publication.OpenError ): ImportError = PublicationError( org.readium.r2.testapp.domain.PublicationError( error diff --git a/test-app/src/main/java/org/readium/r2/testapp/domain/PublicationError.kt b/test-app/src/main/java/org/readium/r2/testapp/domain/PublicationError.kt index 264f5f2aa7..99e00ed541 100644 --- a/test-app/src/main/java/org/readium/r2/testapp/domain/PublicationError.kt +++ b/test-app/src/main/java/org/readium/r2/testapp/domain/PublicationError.kt @@ -45,23 +45,23 @@ sealed class PublicationError(@StringRes userMessageId: Int) : UserException(use companion object { - operator fun invoke(error: Publication.OpeningException): PublicationError = + operator fun invoke(error: Publication.OpenError): PublicationError = when (error) { - is Publication.OpeningException.Forbidden -> + is Publication.OpenError.Forbidden -> Forbidden(error) - is Publication.OpeningException.IncorrectCredentials -> + is Publication.OpenError.IncorrectCredentials -> IncorrectCredentials(error) - is Publication.OpeningException.NotFound -> + is Publication.OpenError.NotFound -> NotFound(error) - is Publication.OpeningException.OutOfMemory -> + is Publication.OpenError.OutOfMemory -> OutOfMemory(error) - is Publication.OpeningException.ParsingFailed -> + is Publication.OpenError.InvalidAsset -> InvalidPublication(error) - is Publication.OpeningException.Unavailable -> + is Publication.OpenError.Unavailable -> Unavailable(error) - is Publication.OpeningException.Unexpected -> + is Publication.OpenError.Unknown -> Unexpected(error) - is Publication.OpeningException.UnsupportedAsset -> + is Publication.OpenError.UnsupportedAsset -> UnsupportedAsset(error) } diff --git a/test-app/src/main/java/org/readium/r2/testapp/reader/ReaderRepository.kt b/test-app/src/main/java/org/readium/r2/testapp/reader/ReaderRepository.kt index f1078f1afe..6f90ad09df 100644 --- a/test-app/src/main/java/org/readium/r2/testapp/reader/ReaderRepository.kt +++ b/test-app/src/main/java/org/readium/r2/testapp/reader/ReaderRepository.kt @@ -76,7 +76,7 @@ class ReaderRepository( ) operator fun invoke( - error: Publication.OpeningException + error: Publication.OpenError ): OpeningError = PublicationError( org.readium.r2.testapp.domain.PublicationError( error