summaryrefslogtreecommitdiff
path: root/opendc-web/opendc-web-server
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-web/opendc-web-server')
-rw-r--r--opendc-web/opendc-web-server/build.gradle.kts1
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/QuarkusObjectMapperSupplier.java (renamed from opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonType.kt)33
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt5
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt5
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt5
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt5
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/AbstractJsonSqlTypeDescriptor.kt74
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBinarySqlTypeDescriptor.kt48
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBytesSqlTypeDescriptor.kt88
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonSqlTypeDescriptor.kt110
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonStringSqlTypeDescriptor.kt63
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonTypeDescriptor.kt150
-rw-r--r--opendc-web/opendc-web-server/src/main/resources/hypersistence-utils.properties1
13 files changed, 18 insertions, 570 deletions
diff --git a/opendc-web/opendc-web-server/build.gradle.kts b/opendc-web/opendc-web-server/build.gradle.kts
index 714ab066..62c13591 100644
--- a/opendc-web/opendc-web-server/build.gradle.kts
+++ b/opendc-web/opendc-web-server/build.gradle.kts
@@ -51,6 +51,7 @@ dependencies {
implementation(libs.quarkus.flyway)
implementation(libs.quarkus.jdbc.postgresql)
implementation(libs.quarkus.jdbc.h2)
+ implementation(libs.hypersistence.utils.hibernate)
testImplementation(libs.quarkus.junit5.core)
testImplementation(libs.quarkus.junit5.mockk)
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonType.kt b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/QuarkusObjectMapperSupplier.java
index 9ee21a4c..e46c74ed 100644
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonType.kt
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/QuarkusObjectMapperSupplier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 AtLarge Research
+ * Copyright (c) 2023 AtLarge Research
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,29 +20,20 @@
* SOFTWARE.
*/
-package org.opendc.web.server.util.hibernate.json
+package org.opendc.web.server.util;
-import com.fasterxml.jackson.databind.ObjectMapper
-import org.hibernate.type.AbstractSingleColumnStandardBasicType
-import org.hibernate.type.BasicType
-import org.hibernate.usertype.DynamicParameterizedType
-import java.util.Properties
-import javax.enterprise.inject.spi.CDI
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.hypersistence.utils.hibernate.type.util.ObjectMapperSupplier;
+import io.quarkus.runtime.annotations.RegisterForReflection;
+import javax.enterprise.inject.spi.CDI;
/**
- * A [BasicType] that contains JSON.
+ * A supplier for an {@link ObjectMapper} used by the Hypersistence utilities.
*/
-class JsonType(objectMapper: ObjectMapper) : AbstractSingleColumnStandardBasicType<Any>(JsonSqlTypeDescriptor, JsonTypeDescriptor(objectMapper)), DynamicParameterizedType {
- /**
- * No-arg constructor for Hibernate to instantiate.
- */
- constructor() : this(CDI.current().select(ObjectMapper::class.java).get())
-
- override fun getName(): String = "json"
-
- override fun registerUnderJavaType(): Boolean = true
-
- override fun setParameterValues(parameters: Properties) {
- (javaTypeDescriptor as JsonTypeDescriptor).setParameterValues(parameters)
+@RegisterForReflection
+public class QuarkusObjectMapperSupplier implements ObjectMapperSupplier {
+ @Override
+ public ObjectMapper get() {
+ return CDI.current().select(ObjectMapper.class).get();
}
}
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt
index 84a71acf..9c260fc1 100644
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt
+++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt
@@ -23,9 +23,7 @@
package org.opendc.web.server.model
import org.hibernate.annotations.Type
-import org.hibernate.annotations.TypeDef
import org.opendc.web.proto.JobState
-import org.opendc.web.server.util.hibernate.json.JsonType
import java.time.Instant
import javax.persistence.Column
import javax.persistence.Entity
@@ -42,7 +40,6 @@ import javax.persistence.Table
/**
* A simulation job to be run by the simulator.
*/
-@TypeDef(name = "json", typeClass = JsonType::class)
@Entity
@Table(name = "jobs")
@NamedQueries(
@@ -103,7 +100,7 @@ class Job(
/**
* Experiment results in JSON
*/
- @Type(type = "json")
+ @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType")
@Column(columnDefinition = "jsonb")
var results: Map<String, Any>? = null
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt
index 09437712..edf1205f 100644
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt
+++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt
@@ -23,9 +23,7 @@
package org.opendc.web.server.model
import org.hibernate.annotations.Type
-import org.hibernate.annotations.TypeDef
import org.opendc.web.proto.Targets
-import org.opendc.web.server.util.hibernate.json.JsonType
import javax.persistence.CascadeType
import javax.persistence.Column
import javax.persistence.Entity
@@ -45,7 +43,6 @@ import javax.persistence.UniqueConstraint
/**
* A portfolio is the composition of multiple scenarios.
*/
-@TypeDef(name = "json", typeClass = JsonType::class)
@Entity
@Table(
name = "portfolios",
@@ -85,7 +82,7 @@ class Portfolio(
/**
* The portfolio targets (metrics, repetitions).
*/
- @Type(type = "json")
+ @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType")
@Column(columnDefinition = "jsonb", nullable = false, updatable = false)
val targets: Targets
) {
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt
index 62adc9e2..47c3e8b2 100644
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt
+++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt
@@ -23,9 +23,7 @@
package org.opendc.web.server.model
import org.hibernate.annotations.Type
-import org.hibernate.annotations.TypeDef
import org.opendc.web.proto.OperationalPhenomena
-import org.opendc.web.server.util.hibernate.json.JsonType
import javax.persistence.CascadeType
import javax.persistence.Column
import javax.persistence.Embedded
@@ -45,7 +43,6 @@ import javax.persistence.UniqueConstraint
/**
* A single scenario to be explored by the simulator.
*/
-@TypeDef(name = "json", typeClass = JsonType::class)
@Entity
@Table(
name = "scenarios",
@@ -101,7 +98,7 @@ class Scenario(
@ManyToOne(optional = false)
val topology: Topology,
- @Type(type = "json")
+ @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType")
@Column(columnDefinition = "jsonb", nullable = false, updatable = false)
val phenomena: OperationalPhenomena,
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt
index 26368455..fe48a0f2 100644
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt
+++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt
@@ -23,9 +23,7 @@
package org.opendc.web.server.model
import org.hibernate.annotations.Type
-import org.hibernate.annotations.TypeDef
import org.opendc.web.proto.Room
-import org.opendc.web.server.util.hibernate.json.JsonType
import java.time.Instant
import javax.persistence.Column
import javax.persistence.Entity
@@ -43,7 +41,6 @@ import javax.persistence.UniqueConstraint
/**
* A datacenter design in OpenDC.
*/
-@TypeDef(name = "json", typeClass = JsonType::class)
@Entity
@Table(
name = "topologies",
@@ -86,7 +83,7 @@ class Topology(
/**
* Datacenter design in JSON
*/
- @Type(type = "json")
+ @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType")
@Column(columnDefinition = "jsonb", nullable = false)
var rooms: List<Room> = emptyList()
) {
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/AbstractJsonSqlTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/AbstractJsonSqlTypeDescriptor.kt
deleted file mode 100644
index 9e29b734..00000000
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/AbstractJsonSqlTypeDescriptor.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2022 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.web.server.util.hibernate.json
-
-import org.hibernate.type.descriptor.ValueExtractor
-import org.hibernate.type.descriptor.WrapperOptions
-import org.hibernate.type.descriptor.java.JavaTypeDescriptor
-import org.hibernate.type.descriptor.sql.BasicExtractor
-import org.hibernate.type.descriptor.sql.SqlTypeDescriptor
-import java.sql.CallableStatement
-import java.sql.ResultSet
-import java.sql.Types
-
-/**
- * Abstract implementation of a [SqlTypeDescriptor] for Hibernate JSON type.
- */
-internal abstract class AbstractJsonSqlTypeDescriptor : SqlTypeDescriptor {
-
- override fun getSqlType(): Int {
- return Types.OTHER
- }
-
- override fun canBeRemapped(): Boolean {
- return true
- }
-
- override fun <X> getExtractor(typeDescriptor: JavaTypeDescriptor<X>): ValueExtractor<X> {
- return object : BasicExtractor<X>(typeDescriptor, this) {
- override fun doExtract(rs: ResultSet, name: String, options: WrapperOptions): X {
- return typeDescriptor.wrap(extractJson(rs, name), options)
- }
-
- override fun doExtract(statement: CallableStatement, index: Int, options: WrapperOptions): X {
- return typeDescriptor.wrap(extractJson(statement, index), options)
- }
-
- override fun doExtract(statement: CallableStatement, name: String, options: WrapperOptions): X {
- return typeDescriptor.wrap(extractJson(statement, name), options)
- }
- }
- }
-
- open fun extractJson(rs: ResultSet, name: String): Any? {
- return rs.getObject(name)
- }
-
- open fun extractJson(statement: CallableStatement, index: Int): Any? {
- return statement.getObject(index)
- }
-
- open fun extractJson(statement: CallableStatement, name: String): Any? {
- return statement.getObject(name)
- }
-}
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBinarySqlTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBinarySqlTypeDescriptor.kt
deleted file mode 100644
index df6a3013..00000000
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBinarySqlTypeDescriptor.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2022 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.web.server.util.hibernate.json
-
-import com.fasterxml.jackson.databind.JsonNode
-import org.hibernate.type.descriptor.ValueBinder
-import org.hibernate.type.descriptor.WrapperOptions
-import org.hibernate.type.descriptor.java.JavaTypeDescriptor
-import org.hibernate.type.descriptor.sql.BasicBinder
-import java.sql.CallableStatement
-import java.sql.PreparedStatement
-
-/**
- * A [AbstractJsonSqlTypeDescriptor] that stores the JSON as binary (JSONB).
- */
-internal object JsonBinarySqlTypeDescriptor : AbstractJsonSqlTypeDescriptor() {
- override fun <X> getBinder(typeDescriptor: JavaTypeDescriptor<X>): ValueBinder<X> {
- return object : BasicBinder<X>(typeDescriptor, this) {
- override fun doBind(st: PreparedStatement, value: X, index: Int, options: WrapperOptions) {
- st.setObject(index, typeDescriptor.unwrap(value, JsonNode::class.java, options), sqlType)
- }
-
- override fun doBind(st: CallableStatement, value: X, name: String, options: WrapperOptions) {
- st.setObject(name, typeDescriptor.unwrap(value, JsonNode::class.java, options), sqlType)
- }
- }
- }
-}
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBytesSqlTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBytesSqlTypeDescriptor.kt
deleted file mode 100644
index 4924f586..00000000
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBytesSqlTypeDescriptor.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2022 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.web.server.util.hibernate.json
-
-import org.hibernate.type.descriptor.ValueBinder
-import org.hibernate.type.descriptor.WrapperOptions
-import org.hibernate.type.descriptor.java.JavaTypeDescriptor
-import org.hibernate.type.descriptor.sql.BasicBinder
-import java.io.UnsupportedEncodingException
-import java.sql.CallableStatement
-import java.sql.PreparedStatement
-import java.sql.ResultSet
-import java.sql.Types
-
-/**
- * A [AbstractJsonSqlTypeDescriptor] that stores the JSON as UTF-8 encoded bytes.
- */
-internal object JsonBytesSqlTypeDescriptor : AbstractJsonSqlTypeDescriptor() {
- private val CHARSET = Charsets.UTF_8
-
- override fun getSqlType(): Int {
- return Types.BINARY
- }
-
- override fun <X> getBinder(javaTypeDescriptor: JavaTypeDescriptor<X>): ValueBinder<X> {
- return object : BasicBinder<X>(javaTypeDescriptor, this) {
- override fun doBind(st: PreparedStatement, value: X, index: Int, options: WrapperOptions) {
- st.setBytes(index, toJsonBytes(javaTypeDescriptor.unwrap(value, String::class.java, options)))
- }
-
- override fun doBind(st: CallableStatement, value: X, name: String, options: WrapperOptions) {
- st.setBytes(name, toJsonBytes(javaTypeDescriptor.unwrap(value, String::class.java, options)))
- }
- }
- }
-
- override fun extractJson(rs: ResultSet, name: String): Any? {
- return fromJsonBytes(rs.getBytes(name))
- }
-
- override fun extractJson(statement: CallableStatement, index: Int): Any? {
- return fromJsonBytes(statement.getBytes(index))
- }
-
- override fun extractJson(statement: CallableStatement, name: String): Any? {
- return fromJsonBytes(statement.getBytes(name))
- }
-
- private fun toJsonBytes(jsonValue: String): ByteArray? {
- return try {
- jsonValue.toByteArray(CHARSET)
- } catch (e: UnsupportedEncodingException) {
- throw IllegalStateException(e)
- }
- }
-
- private fun fromJsonBytes(jsonBytes: ByteArray?): String? {
- return if (jsonBytes == null) {
- null
- } else {
- try {
- String(jsonBytes, CHARSET)
- } catch (e: UnsupportedEncodingException) {
- throw IllegalStateException(e)
- }
- }
- }
-}
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonSqlTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonSqlTypeDescriptor.kt
deleted file mode 100644
index bd22ffbe..00000000
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonSqlTypeDescriptor.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2022 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.web.server.util.hibernate.json
-
-import org.hibernate.dialect.H2Dialect
-import org.hibernate.dialect.PostgreSQL81Dialect
-import org.hibernate.internal.SessionImpl
-import org.hibernate.type.descriptor.ValueBinder
-import org.hibernate.type.descriptor.ValueExtractor
-import org.hibernate.type.descriptor.WrapperOptions
-import org.hibernate.type.descriptor.java.JavaTypeDescriptor
-import org.hibernate.type.descriptor.sql.BasicBinder
-import org.hibernate.type.descriptor.sql.BasicExtractor
-import org.hibernate.type.descriptor.sql.SqlTypeDescriptor
-import java.sql.CallableStatement
-import java.sql.PreparedStatement
-import java.sql.ResultSet
-import java.sql.Types
-
-/**
- * A [SqlTypeDescriptor] that automatically selects the correct implementation for the database dialect.
- */
-internal object JsonSqlTypeDescriptor : SqlTypeDescriptor {
-
- override fun getSqlType(): Int = Types.OTHER
-
- override fun canBeRemapped(): Boolean = true
-
- override fun <X> getExtractor(javaTypeDescriptor: JavaTypeDescriptor<X>): ValueExtractor<X> {
- return object : BasicExtractor<X>(javaTypeDescriptor, this) {
- private var delegate: AbstractJsonSqlTypeDescriptor? = null
-
- override fun doExtract(rs: ResultSet, name: String, options: WrapperOptions): X {
- return javaTypeDescriptor.wrap(delegate(options).extractJson(rs, name), options)
- }
-
- override fun doExtract(statement: CallableStatement, index: Int, options: WrapperOptions): X {
- return javaTypeDescriptor.wrap(delegate(options).extractJson(statement, index), options)
- }
-
- override fun doExtract(statement: CallableStatement, name: String, options: WrapperOptions): X {
- return javaTypeDescriptor.wrap(delegate(options).extractJson(statement, name), options)
- }
-
- private fun delegate(options: WrapperOptions): AbstractJsonSqlTypeDescriptor {
- var delegate = delegate
- if (delegate == null) {
- delegate = resolveSqlTypeDescriptor(options)
- this.delegate = delegate
- }
- return delegate
- }
- }
- }
-
- override fun <X> getBinder(javaTypeDescriptor: JavaTypeDescriptor<X>): ValueBinder<X> {
- return object : BasicBinder<X>(javaTypeDescriptor, this) {
- private var delegate: ValueBinder<X>? = null
-
- override fun doBind(st: PreparedStatement, value: X, index: Int, options: WrapperOptions) {
- delegate(options).bind(st, value, index, options)
- }
-
- override fun doBind(st: CallableStatement, value: X, name: String, options: WrapperOptions) {
- delegate(options).bind(st, value, name, options)
- }
-
- private fun delegate(options: WrapperOptions): ValueBinder<X> {
- var delegate = delegate
- if (delegate == null) {
- delegate = checkNotNull(resolveSqlTypeDescriptor(options).getBinder(javaTypeDescriptor))
- this.delegate = delegate
- }
- return delegate
- }
- }
- }
-
- /**
- * Helper method to resolve the appropriate [SqlTypeDescriptor] based on the [WrapperOptions].
- */
- private fun resolveSqlTypeDescriptor(options: WrapperOptions): AbstractJsonSqlTypeDescriptor {
- val session = options as? SessionImpl
- return when (session?.jdbcServices?.dialect) {
- is PostgreSQL81Dialect -> JsonBinarySqlTypeDescriptor
- is H2Dialect -> JsonBytesSqlTypeDescriptor
- else -> JsonStringSqlTypeDescriptor
- }
- }
-}
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonStringSqlTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonStringSqlTypeDescriptor.kt
deleted file mode 100644
index 6e015762..00000000
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonStringSqlTypeDescriptor.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2022 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.web.server.util.hibernate.json
-
-import org.hibernate.type.descriptor.ValueBinder
-import org.hibernate.type.descriptor.WrapperOptions
-import org.hibernate.type.descriptor.java.JavaTypeDescriptor
-import org.hibernate.type.descriptor.sql.BasicBinder
-import java.sql.CallableStatement
-import java.sql.PreparedStatement
-import java.sql.ResultSet
-import java.sql.Types
-
-/**
- * A [AbstractJsonSqlTypeDescriptor] that stores the JSON as string (VARCHAR).
- */
-internal object JsonStringSqlTypeDescriptor : AbstractJsonSqlTypeDescriptor() {
- override fun getSqlType(): Int = Types.VARCHAR
-
- override fun <X> getBinder(typeDescriptor: JavaTypeDescriptor<X>): ValueBinder<X> {
- return object : BasicBinder<X>(typeDescriptor, this) {
- override fun doBind(st: PreparedStatement, value: X, index: Int, options: WrapperOptions) {
- st.setString(index, typeDescriptor.unwrap(value, String::class.java, options))
- }
-
- override fun doBind(st: CallableStatement, value: X, name: String, options: WrapperOptions) {
- st.setString(name, typeDescriptor.unwrap(value, String::class.java, options))
- }
- }
- }
-
- override fun extractJson(rs: ResultSet, name: String): Any? {
- return rs.getString(name)
- }
-
- override fun extractJson(statement: CallableStatement, index: Int): Any? {
- return statement.getString(index)
- }
-
- override fun extractJson(statement: CallableStatement, name: String): Any? {
- return statement.getString(name)
- }
-}
diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonTypeDescriptor.kt
deleted file mode 100644
index 9407f940..00000000
--- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonTypeDescriptor.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2022 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.web.server.util.hibernate.json
-
-import com.fasterxml.jackson.databind.ObjectMapper
-import org.hibernate.HibernateException
-import org.hibernate.annotations.common.reflection.XProperty
-import org.hibernate.annotations.common.reflection.java.JavaXMember
-import org.hibernate.engine.jdbc.BinaryStream
-import org.hibernate.engine.jdbc.internal.BinaryStreamImpl
-import org.hibernate.type.descriptor.WrapperOptions
-import org.hibernate.type.descriptor.java.AbstractTypeDescriptor
-import org.hibernate.type.descriptor.java.BlobTypeDescriptor
-import org.hibernate.type.descriptor.java.DataHelper
-import org.hibernate.type.descriptor.java.MutableMutabilityPlan
-import org.hibernate.usertype.DynamicParameterizedType
-import java.io.ByteArrayInputStream
-import java.io.IOException
-import java.io.InputStream
-import java.lang.reflect.Type
-import java.sql.Blob
-import java.sql.SQLException
-import java.util.Objects
-import java.util.Properties
-
-/**
- * An [AbstractTypeDescriptor] implementation for Hibernate JSON type.
- */
-internal class JsonTypeDescriptor(private val objectMapper: ObjectMapper) : AbstractTypeDescriptor<Any>(Any::class.java, JsonMutabilityPlan(objectMapper)), DynamicParameterizedType {
- private var type: Type? = null
-
- override fun setParameterValues(parameters: Properties) {
- val xProperty = parameters[DynamicParameterizedType.XPROPERTY] as XProperty
- type = if (xProperty is JavaXMember) {
- val x = xProperty as JavaXMember
- x.javaType
- } else {
- (parameters[DynamicParameterizedType.PARAMETER_TYPE] as DynamicParameterizedType.ParameterType).returnedClass
- }
- }
-
- override fun areEqual(one: Any?, another: Any?): Boolean {
- return when {
- one === another -> true
- one == null || another == null -> false
- one is String && another is String -> one == another
- one is Collection<*> && another is Collection<*> -> Objects.equals(one, another)
- else -> areJsonEqual(one, another)
- }
- }
-
- override fun toString(value: Any?): String {
- return objectMapper.writeValueAsString(value)
- }
-
- override fun fromString(string: String): Any? {
- return objectMapper.readValue(string, objectMapper.typeFactory.constructType(type))
- }
-
- override fun <X> unwrap(value: Any?, type: Class<X>, options: WrapperOptions): X? {
- if (value == null) {
- return null
- }
-
- @Suppress("UNCHECKED_CAST")
- return when {
- String::class.java.isAssignableFrom(type) -> toString(value)
- BinaryStream::class.java.isAssignableFrom(type) || ByteArray::class.java.isAssignableFrom(type) -> {
- val stringValue = if (value is String) value else toString(value)
- BinaryStreamImpl(DataHelper.extractBytes(ByteArrayInputStream(stringValue.toByteArray())))
- }
- Blob::class.java.isAssignableFrom(type) -> {
- val stringValue = if (value is String) value else toString(value)
- BlobTypeDescriptor.INSTANCE.fromString(stringValue)
- }
- Any::class.java.isAssignableFrom(type) -> toJsonType(value)
- else -> throw unknownUnwrap(type)
- } as X
- }
-
- override fun <X> wrap(value: X?, options: WrapperOptions): Any? {
- if (value == null) {
- return null
- }
-
- var blob: Blob? = null
- if (Blob::class.java.isAssignableFrom(value.javaClass)) {
- blob = options.lobCreator.wrap(value as Blob?)
- } else if (ByteArray::class.java.isAssignableFrom(value.javaClass)) {
- blob = options.lobCreator.createBlob(value as ByteArray?)
- } else if (InputStream::class.java.isAssignableFrom(value.javaClass)) {
- val inputStream = value as InputStream
- blob = try {
- options.lobCreator.createBlob(inputStream, inputStream.available().toLong())
- } catch (e: IOException) {
- throw unknownWrap(value.javaClass)
- }
- }
-
- val stringValue: String = try {
- if (blob != null) String(DataHelper.extractBytes(blob.binaryStream)) else value.toString()
- } catch (e: SQLException) {
- throw HibernateException("Unable to extract binary stream from Blob", e)
- }
-
- return fromString(stringValue)
- }
-
- private class JsonMutabilityPlan(private val objectMapper: ObjectMapper) : MutableMutabilityPlan<Any>() {
- override fun deepCopyNotNull(value: Any): Any {
- return objectMapper.treeToValue(objectMapper.valueToTree(value), value.javaClass)
- }
- }
-
- private fun readObject(value: String): Any {
- return objectMapper.readTree(value)
- }
-
- private fun areJsonEqual(one: Any, another: Any): Boolean {
- return readObject(objectMapper.writeValueAsString(one)) == readObject(objectMapper.writeValueAsString(another))
- }
-
- private fun toJsonType(value: Any?): Any {
- return try {
- readObject(objectMapper.writeValueAsString(value))
- } catch (e: Exception) {
- throw IllegalArgumentException(e)
- }
- }
-}
diff --git a/opendc-web/opendc-web-server/src/main/resources/hypersistence-utils.properties b/opendc-web/opendc-web-server/src/main/resources/hypersistence-utils.properties
new file mode 100644
index 00000000..451ce2d8
--- /dev/null
+++ b/opendc-web/opendc-web-server/src/main/resources/hypersistence-utils.properties
@@ -0,0 +1 @@
+hypersistence.utils.jackson.object.mapper=org.opendc.web.server.util.QuarkusObjectMapperSupplier