Skip to content

Commit 374c9c3

Browse files
authored
Replace Date with Instant (readium#506)
1 parent 2cc906c commit 374c9c3

File tree

34 files changed

+310
-221
lines changed

34 files changed

+310
-221
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ All notable changes to this project will be documented in this file. Take a look
1212

1313
* All the `completion` parameters of the `Navigator` APIs are removed.
1414

15+
### Changed
16+
17+
* All the APIs using or returning a `Date` objects are now using a custom `Instant` type.
18+
1519
### Fixed
1620

1721
#### Navigator

docs/migration-guide.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ All migration steps necessary in reading apps to upgrade to major versions of th
88

99
If you target Android devices running below API 26, you now must enable [core library desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring) in your application module.
1010

11+
### Removing JVM dependencies
12+
13+
To reduce our depency to the JVM, we no longer use `Date` objects in the toolkit. Instead, we added a custom `Instant` type.
14+
15+
You can still translate from and to a `Date` object with `Instant.fromJavaDate()` and `instant.toJavaDate()`.
16+
1117

1218
## 3.0.0-alpha.2
1319

readium/lcp/src/main/java/org/readium/r2/lcp/LcpError.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
package org.readium.r2.lcp
88

99
import java.net.SocketTimeoutException
10-
import java.util.*
1110
import kotlinx.coroutines.CancellationException
1211
import org.readium.r2.lcp.service.NetworkException
1312
import org.readium.r2.shared.util.DebugError
1413
import org.readium.r2.shared.util.Error
1514
import org.readium.r2.shared.util.ErrorException
15+
import org.readium.r2.shared.util.Instant
1616
import org.readium.r2.shared.util.ThrowableError
1717
import org.readium.r2.shared.util.Url
1818

@@ -72,16 +72,16 @@ public sealed class LcpError(
7272
cause: Error? = null
7373
) : LcpError(message, cause) {
7474

75-
public class Cancelled(public val date: Date) :
75+
public class Cancelled(public val date: Instant) :
7676
LicenseStatus("This license was cancelled on $date")
7777

78-
public class Returned(public val date: Date) :
78+
public class Returned(public val date: Instant) :
7979
LicenseStatus("This license has been returned on $date")
8080

81-
public class NotStarted(public val start: Date) :
81+
public class NotStarted(public val start: Instant) :
8282
LicenseStatus("This license starts on $start")
8383

84-
public class Expired(public val end: Date) :
84+
public class Expired(public val end: Instant) :
8585
LicenseStatus("This license expired on $end")
8686

8787
/**
@@ -90,7 +90,7 @@ public sealed class LcpError(
9090
* in the status document. If no event is logged in the status document, no such message should
9191
* appear (certainly not "The license was registered by 0 devices").
9292
*/
93-
public class Revoked(public val date: Date, public val devicesCount: Int) :
93+
public class Revoked(public val date: Instant, public val devicesCount: Int) :
9494
LicenseStatus(
9595
"This license was revoked by its provider on $date. It was registered by $devicesCount device(s)."
9696
)
@@ -109,7 +109,7 @@ public sealed class LcpError(
109109
Renew("Publication could not be renewed properly")
110110

111111
/** Incorrect renewal period, your publication could not be renewed. */
112-
public class InvalidRenewalPeriod(public val maxRenewDate: Date?) :
112+
public class InvalidRenewalPeriod(public val maxRenewDate: Instant?) :
113113
Renew("Incorrect renewal period, your publication could not be renewed")
114114

115115
/** An unexpected error has occurred on the licensing server. */

readium/lcp/src/main/java/org/readium/r2/lcp/LcpLicense.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
package org.readium.r2.lcp
88

99
import java.net.URL
10-
import java.util.*
1110
import kotlinx.coroutines.DelicateCoroutinesApi
1211
import kotlinx.coroutines.GlobalScope
1312
import kotlinx.coroutines.flow.StateFlow
@@ -18,6 +17,7 @@ import org.readium.r2.lcp.license.model.LicenseDocument
1817
import org.readium.r2.lcp.license.model.StatusDocument
1918
import org.readium.r2.shared.publication.services.ContentProtectionService
2019
import org.readium.r2.shared.util.Closeable
20+
import org.readium.r2.shared.util.Instant
2121
import org.readium.r2.shared.util.Try
2222
import org.readium.r2.shared.util.Url
2323
import org.readium.r2.shared.util.toDebugDescription
@@ -59,15 +59,15 @@ public interface LcpLicense : ContentProtectionService.UserRights, Closeable {
5959
* The maximum potential date to renew to.
6060
* If null, then the renew date might not be customizable.
6161
*/
62-
public val maxRenewDate: Date?
62+
public val maxRenewDate: Instant?
6363

6464
/**
6565
* Renews the loan by starting a renew LSD interaction.
6666
*
6767
* @param prefersWebPage Indicates whether the loan should be renewed through a web page if
6868
* available, instead of programmatically.
6969
*/
70-
public suspend fun renewLoan(listener: RenewListener, prefersWebPage: Boolean = false): Try<Date?, LcpError>
70+
public suspend fun renewLoan(listener: RenewListener, prefersWebPage: Boolean = false): Try<Instant?, LcpError>
7171

7272
/**
7373
* Can the user return the loaned publication?
@@ -98,7 +98,7 @@ public interface LcpLicense : ContentProtectionService.UserRights, Closeable {
9898
*
9999
* The returned date can't exceed [maximumDate].
100100
*/
101-
public suspend fun preferredEndDate(maximumDate: Date?): Date?
101+
public suspend fun preferredEndDate(maximumDate: Instant?): Instant?
102102

103103
/**
104104
* Called when the renew interaction uses an HTML web page.

readium/lcp/src/main/java/org/readium/r2/lcp/MaterialRenewListener.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ import androidx.activity.result.contract.ActivityResultContracts
1212
import androidx.browser.customtabs.CustomTabsIntent
1313
import androidx.fragment.app.FragmentManager
1414
import com.google.android.material.datepicker.*
15-
import java.util.*
1615
import kotlin.coroutines.Continuation
1716
import kotlin.coroutines.resume
1817
import kotlin.coroutines.suspendCoroutine
1918
import kotlinx.coroutines.suspendCancellableCoroutine
19+
import org.readium.r2.shared.util.Instant
2020
import org.readium.r2.shared.util.Url
2121

2222
/**
@@ -37,9 +37,9 @@ public class MaterialRenewListener(
3737
private val fragmentManager: FragmentManager
3838
) : LcpLicense.RenewListener {
3939

40-
override suspend fun preferredEndDate(maximumDate: Date?): Date? = suspendCancellableCoroutine { cont ->
41-
val start = (license.license.rights.end ?: Date()).time
42-
val end = maximumDate?.time
40+
override suspend fun preferredEndDate(maximumDate: Instant?): Instant? = suspendCancellableCoroutine { cont ->
41+
val start = (license.license.rights.end ?: Instant.now()).toEpochMilliseconds()
42+
val end = maximumDate?.toEpochMilliseconds()
4343

4444
MaterialDatePicker.Builder.datePicker()
4545
.setCalendarConstraints(
@@ -67,7 +67,7 @@ public class MaterialRenewListener(
6767
addOnNegativeButtonClickListener { cont.cancel() }
6868

6969
addOnPositiveButtonClickListener { selection ->
70-
cont.resume(Date(selection))
70+
cont.resume(Instant.fromEpochMilliseconds(selection))
7171
}
7272
}
7373
.show(fragmentManager, "MaterialRenewListener.DatePicker")

readium/lcp/src/main/java/org/readium/r2/lcp/license/License.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
package org.readium.r2.lcp.license
1111

1212
import java.net.HttpURLConnection
13-
import java.util.Date
1413
import kotlinx.coroutines.CancellationException
1514
import kotlinx.coroutines.CoroutineScope
1615
import kotlinx.coroutines.Dispatchers
@@ -30,8 +29,8 @@ import org.readium.r2.lcp.service.DeviceService
3029
import org.readium.r2.lcp.service.LcpClient
3130
import org.readium.r2.lcp.service.LicensesRepository
3231
import org.readium.r2.lcp.service.NetworkService
33-
import org.readium.r2.shared.extensions.toIso8601String
3432
import org.readium.r2.shared.extensions.tryOrNull
33+
import org.readium.r2.shared.util.Instant
3534
import org.readium.r2.shared.util.Try
3635
import org.readium.r2.shared.util.getOrElse
3736
import org.readium.r2.shared.util.getOrThrow
@@ -144,10 +143,10 @@ internal class License private constructor(
144143
override val canRenewLoan: Boolean
145144
get() = status?.link(StatusDocument.Rel.Renew) != null
146145

147-
override val maxRenewDate: Date?
146+
override val maxRenewDate: Instant?
148147
get() = status?.potentialRights?.end
149148

150-
override suspend fun renewLoan(listener: LcpLicense.RenewListener, prefersWebPage: Boolean): Try<Date?, LcpError> {
149+
override suspend fun renewLoan(listener: LcpLicense.RenewListener, prefersWebPage: Boolean): Try<Instant?, LcpError> {
151150
// Finds the renew link according to `prefersWebPage`.
152151
fun findRenewLink(): Link? {
153152
val status = documents.status ?: return null
@@ -179,7 +178,7 @@ internal class License private constructor(
179178

180179
val parameters = this.device.asQueryParameters.toMutableMap()
181180
if (endDate != null) {
182-
parameters["end"] = endDate.toIso8601String()
181+
parameters["end"] = endDate.toString()
183182
}
184183

185184
val url = link.url(parameters = parameters)

readium/lcp/src/main/java/org/readium/r2/lcp/license/LicenseValidation.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import org.readium.r2.lcp.service.DeviceService
2424
import org.readium.r2.lcp.service.LcpClient
2525
import org.readium.r2.lcp.service.NetworkService
2626
import org.readium.r2.lcp.service.PassphrasesService
27+
import org.readium.r2.shared.util.Instant
2728
import org.readium.r2.shared.util.getOrElse
2829
import org.readium.r2.shared.util.mediatype.MediaType
2930
import timber.log.Timber
@@ -388,7 +389,7 @@ internal class LicenseValidation(
388389
statusDocumentTakesPrecedence: Boolean
389390
) {
390391
var error: LcpError.LicenseStatus? = null
391-
val now = Date()
392+
val now = Instant.now()
392393
val start = license.rights.start ?: now
393394
val end = license.rights.end ?: now
394395
val isLicenseExpired = (start > now || now > end)

readium/lcp/src/main/java/org/readium/r2/lcp/license/model/LicenseDocument.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
package org.readium.r2.lcp.license.model
1111

1212
import java.nio.charset.Charset
13-
import java.util.*
1413
import org.json.JSONObject
1514
import org.readium.r2.lcp.LcpError
1615
import org.readium.r2.lcp.LcpException
@@ -21,9 +20,9 @@ import org.readium.r2.lcp.license.model.components.lcp.Rights
2120
import org.readium.r2.lcp.license.model.components.lcp.Signature
2221
import org.readium.r2.lcp.license.model.components.lcp.User
2322
import org.readium.r2.lcp.service.URLParameters
24-
import org.readium.r2.shared.extensions.iso8601ToDate
2523
import org.readium.r2.shared.extensions.optNullableString
2624
import org.readium.r2.shared.util.AbsoluteUrl
25+
import org.readium.r2.shared.util.Instant
2726
import org.readium.r2.shared.util.Try
2827
import org.readium.r2.shared.util.Url
2928
import org.readium.r2.shared.util.mediatype.MediaType
@@ -63,14 +62,14 @@ public class LicenseDocument internal constructor(public val json: JSONObject) {
6362
json.optNullableString("id")
6463
?: throw LcpException(LcpError.Parsing.LicenseDocument)
6564

66-
public val issued: Date =
65+
public val issued: Instant =
6766
json.optNullableString("issued")
68-
?.iso8601ToDate()
67+
?.let { Instant.parse(it) }
6968
?: throw LcpException(LcpError.Parsing.LicenseDocument)
7069

71-
public val updated: Date =
70+
public val updated: Instant =
7271
json.optNullableString("updated")
73-
?.iso8601ToDate()
72+
?.let { Instant.parse(it) }
7473
?: issued
7574

7675
public val encryption: Encryption =

readium/lcp/src/main/java/org/readium/r2/lcp/license/model/StatusDocument.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,18 @@ import org.readium.r2.lcp.license.model.components.Links
1919
import org.readium.r2.lcp.license.model.components.lsd.Event
2020
import org.readium.r2.lcp.license.model.components.lsd.PotentialRights
2121
import org.readium.r2.lcp.service.URLParameters
22-
import org.readium.r2.shared.extensions.iso8601ToDate
2322
import org.readium.r2.shared.extensions.mapNotNull
2423
import org.readium.r2.shared.extensions.optNullableString
24+
import org.readium.r2.shared.util.Instant
2525
import org.readium.r2.shared.util.Url
2626
import org.readium.r2.shared.util.mediatype.MediaType
2727

2828
public class StatusDocument(public val data: ByteArray) {
2929
public val id: String
3030
public val status: Status
3131
public val message: String
32-
public val licenseUpdated: Date
33-
public val statusUpdated: Date
32+
public val licenseUpdated: Instant
33+
public val statusUpdated: Instant
3434
public val links: Links
3535
public val potentialRights: PotentialRights?
3636
public val events: List<Event>
@@ -49,7 +49,7 @@ public class StatusDocument(public val data: ByteArray) {
4949
public val rawValue: String get() = value
5050

5151
public companion object {
52-
public operator fun invoke(value: String): Status? = values().firstOrNull { it.value == value }
52+
public operator fun invoke(value: String): Status? = entries.firstOrNull { it.value == value }
5353
}
5454
}
5555

@@ -63,7 +63,7 @@ public class StatusDocument(public val data: ByteArray) {
6363
public val rawValue: String get() = value
6464

6565
public companion object {
66-
public operator fun invoke(value: String): Rel? = values().firstOrNull { it.value == value }
66+
public operator fun invoke(value: String): Rel? = entries.firstOrNull { it.value == value }
6767
}
6868
}
6969

@@ -83,10 +83,10 @@ public class StatusDocument(public val data: ByteArray) {
8383
)
8484

8585
val updated = json.optJSONObject("updated") ?: JSONObject()
86-
licenseUpdated = updated.optNullableString("license")?.iso8601ToDate() ?: throw LcpException(
86+
licenseUpdated = updated.optNullableString("license")?.let { Instant.parse(it) } ?: throw LcpException(
8787
LcpError.Parsing.StatusDocument
8888
)
89-
statusUpdated = updated.optNullableString("status")?.iso8601ToDate() ?: throw LcpException(
89+
statusUpdated = updated.optNullableString("status")?.let { Instant.parse(it) } ?: throw LcpException(
9090
LcpError.Parsing.StatusDocument
9191
)
9292

readium/lcp/src/main/java/org/readium/r2/lcp/license/model/components/lcp/Rights.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,25 @@
99

1010
package org.readium.r2.lcp.license.model.components.lcp
1111

12-
import java.util.*
1312
import org.json.JSONObject
14-
import org.readium.r2.shared.extensions.iso8601ToDate
1513
import org.readium.r2.shared.extensions.optNullableInt
1614
import org.readium.r2.shared.extensions.optNullableString
15+
import org.readium.r2.shared.util.Instant
1716

1817
public data class Rights(val json: JSONObject) {
1918
val print: Int?
2019
val copy: Int?
21-
val start: Date?
22-
val end: Date?
20+
val start: Instant?
21+
val end: Instant?
2322
val extensions: JSONObject
2423

2524
init {
2625
val clone = JSONObject(json.toString())
2726

2827
print = clone.optNullableInt("print", remove = true)
2928
copy = clone.optNullableInt("copy", remove = true)
30-
start = clone.optNullableString("start", remove = true)?.iso8601ToDate()
31-
end = clone.optNullableString("end", remove = true)?.iso8601ToDate()
29+
start = clone.optNullableString("start", remove = true)?.let { Instant.parse(it) }
30+
end = clone.optNullableString("end", remove = true)?.let { Instant.parse(it) }
3231

3332
extensions = clone
3433
}

0 commit comments

Comments
 (0)