aboutsummaryrefslogtreecommitdiff
path: root/ebics
diff options
context:
space:
mode:
authorAntoine A <>2024-02-13 07:47:46 +0100
committerAntoine A <>2024-02-13 07:47:46 +0100
commitf83a22f243a315fbc4b4086155c2401845cf334c (patch)
treeaf264e686c5fc657fba060e210bdfdb3454cbf72 /ebics
parent7f84324c0712097513becd7c4675e50d4194833a (diff)
downloadlibeufin-f83a22f243a315fbc4b4086155c2401845cf334c.tar.gz
libeufin-f83a22f243a315fbc4b4086155c2401845cf334c.tar.bz2
libeufin-f83a22f243a315fbc4b4086155c2401845cf334c.zip
Optimize memory usage and performance by using ByteArray when possible and improve logging
Diffstat (limited to 'ebics')
-rw-r--r--ebics/src/main/kotlin/Ebics.kt10
-rw-r--r--ebics/src/main/kotlin/EbicsOrderUtil.kt4
-rw-r--r--ebics/src/main/kotlin/XMLUtil.kt56
-rw-r--r--ebics/src/main/kotlin/ebics_h004/EbicsRequest.kt9
-rw-r--r--ebics/src/main/kotlin/ebics_h005/Ebics3Request.kt7
-rw-r--r--ebics/src/test/kotlin/EbicsMessagesTest.kt50
-rw-r--r--ebics/src/test/kotlin/EbicsOrderUtilTest.kt4
-rw-r--r--ebics/src/test/kotlin/XmlUtilTest.kt22
8 files changed, 68 insertions, 94 deletions
diff --git a/ebics/src/main/kotlin/Ebics.kt b/ebics/src/main/kotlin/Ebics.kt
index 406da44c..91a41022 100644
--- a/ebics/src/main/kotlin/Ebics.kt
+++ b/ebics/src/main/kotlin/Ebics.kt
@@ -310,7 +310,7 @@ class HpbResponseData(
fun parseEbicsHpbOrder(orderDataRaw: ByteArray): HpbResponseData {
val resp = try {
- XMLUtil.convertStringToJaxb<HPBResponseOrderData>(orderDataRaw.toString(Charsets.UTF_8))
+ XMLUtil.convertBytesToJaxb<HPBResponseOrderData>(orderDataRaw)
} catch (e: Exception) {
throw EbicsProtocolError(HttpStatusCode.InternalServerError, "Invalid XML (as HPB response) received from bank")
}
@@ -331,10 +331,10 @@ fun parseEbicsHpbOrder(orderDataRaw: ByteArray): HpbResponseData {
)
}
-fun ebics3toInternalRepr(response: String): EbicsResponseContent {
+fun ebics3toInternalRepr(response: ByteArray): EbicsResponseContent {
// logger.debug("Converting bank resp to internal repr.: $response")
val resp: JAXBElement<Ebics3Response> = try {
- XMLUtil.convertStringToJaxb(response)
+ XMLUtil.convertBytesToJaxb(response)
} catch (e: Exception) {
throw EbicsProtocolError(
HttpStatusCode.InternalServerError,
@@ -368,9 +368,9 @@ fun ebics3toInternalRepr(response: String): EbicsResponseContent {
)
}
-fun ebics25toInternalRepr(response: String): EbicsResponseContent {
+fun ebics25toInternalRepr(response: ByteArray): EbicsResponseContent {
val resp: JAXBElement<EbicsResponse> = try {
- XMLUtil.convertStringToJaxb(response)
+ XMLUtil.convertBytesToJaxb(response)
} catch (e: Exception) {
throw EbicsProtocolError(
HttpStatusCode.InternalServerError,
diff --git a/ebics/src/main/kotlin/EbicsOrderUtil.kt b/ebics/src/main/kotlin/EbicsOrderUtil.kt
index ef7ed1f7..c056ddde 100644
--- a/ebics/src/main/kotlin/EbicsOrderUtil.kt
+++ b/ebics/src/main/kotlin/EbicsOrderUtil.kt
@@ -39,12 +39,12 @@ object EbicsOrderUtil {
inline fun <reified T> decodeOrderDataXml(encodedOrderData: ByteArray): T {
return InflaterInputStream(encodedOrderData.inputStream()).use {
val bytes = it.readAllBytes()
- XMLUtil.convertStringToJaxb<T>(bytes.toString(Charsets.UTF_8)).value
+ XMLUtil.convertBytesToJaxb<T>(bytes).value
}
}
inline fun <reified T> encodeOrderDataXml(obj: T): ByteArray {
- val bytes = XMLUtil.convertJaxbToString(obj).toByteArray()
+ val bytes = XMLUtil.convertJaxbToBytes(obj)
return DeflaterInputStream(bytes.inputStream()).use {
it.readAllBytes()
}
diff --git a/ebics/src/main/kotlin/XMLUtil.kt b/ebics/src/main/kotlin/XMLUtil.kt
index 63dbf35b..5947341a 100644
--- a/ebics/src/main/kotlin/XMLUtil.kt
+++ b/ebics/src/main/kotlin/XMLUtil.kt
@@ -287,17 +287,17 @@ class XMLUtil private constructor() {
* @param xmlString XML body, as read from the POST body.
* @return InputStream object, as wanted by the validator.
*/
- fun validateFromString(xmlString: String): Boolean {
- val xmlInputStream: InputStream = ByteArrayInputStream(xmlString.toByteArray())
+ fun validateFromBytes(xml: ByteArray): Boolean {
+ val xmlInputStream: InputStream = ByteArrayInputStream(xml)
val xmlSource = StreamSource(xmlInputStream)
return validate(xmlSource)
}
- inline fun <reified T> convertJaxbToString(
+ inline fun <reified T> convertJaxbToBytes(
obj: T,
withSchemaLocation: String? = null
- ): String {
- val sw = StringWriter()
+ ): ByteArray {
+ val w = ByteArrayOutputStream()
val jc = JAXBContext.newInstance(T::class.java)
val m = jc.createMarshaller()
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true)
@@ -305,8 +305,8 @@ class XMLUtil private constructor() {
m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, withSchemaLocation)
}
m.setProperty("com.sun.xml.bind.namespacePrefixMapper", DefaultNamespaces())
- m.marshal(obj, sw)
- return sw.toString()
+ m.marshal(obj, w)
+ return w.toByteArray()
}
inline fun <reified T> convertJaxbToDocument(
@@ -328,37 +328,31 @@ class XMLUtil private constructor() {
}
/**
- * Convert a XML string to the JAXB representation.
+ * Convert XML bytes to the JAXB representation.
*
- * @param documentString the string to convert into JAXB.
+ * @param documentBytes the bytes to convert into JAXB.
* @return the JAXB object reflecting the original XML document.
*/
- inline fun <reified T> convertStringToJaxb(documentString: String): JAXBElement<T> {
+ inline fun <reified T> convertBytesToJaxb(documentBytes: ByteArray): JAXBElement<T> {
val jc = JAXBContext.newInstance(T::class.java)
val u = jc.createUnmarshaller()
return u.unmarshal( /* Marshalling the object into the document. */
- StreamSource(StringReader(documentString)),
+ StreamSource(ByteArrayInputStream(documentBytes)),
T::class.java
)
}
- /**
- * Extract String from DOM.
- *
- * @param document the DOM to extract the string from.
- * @return the final String, or null if errors occur.
- */
- fun convertDomToString(document: Document): String {
+ fun convertDomToBytes(document: Document): ByteArray {
/* Make Transformer. */
val tf = TransformerFactory.newInstance()
val t = tf.newTransformer()
- /* Make string writer. */
- val sw = StringWriter()
+ /* Make bytes writer. */
+ val w = ByteArrayOutputStream()
/* Extract string. */
- t.transform(DOMSource(document), StreamResult(sw))
- return sw.toString()
+ t.transform(DOMSource(document), StreamResult(w))
+ return w.toByteArray()
}
/**
@@ -391,20 +385,6 @@ class XMLUtil private constructor() {
return m.unmarshal(document, finalType) // document "went" into Jaxb
}
- /**
- * Parse string into XML DOM.
- * @param xmlString the string to parse.
- * @return the DOM representing @a xmlString
- */
- fun parseStringIntoDom(xmlString: String): Document {
- val factory = DocumentBuilderFactory.newInstance().apply {
- isNamespaceAware = true
- }
- val xmlInputStream = ByteArrayInputStream(xmlString.toByteArray())
- val builder = factory.newDocumentBuilder()
- return builder.parse(InputSource(xmlInputStream))
- }
-
/** Parse [xml] into a XML DOM */
fun parseBytesIntoDom(xml: ByteArray): Document {
val factory = DocumentBuilderFactory.newInstance().apply {
@@ -415,10 +395,10 @@ class XMLUtil private constructor() {
return builder.parse(InputSource(xmlInputStream))
}
- fun signEbicsResponse(ebicsResponse: EbicsResponse, privateKey: RSAPrivateCrtKey): String {
+ fun signEbicsResponse(ebicsResponse: EbicsResponse, privateKey: RSAPrivateCrtKey): ByteArray {
val doc = convertJaxbToDocument(ebicsResponse)
signEbicsDocument(doc, privateKey)
- val signedDoc = XMLUtil.convertDomToString(doc)
+ val signedDoc = XMLUtil.convertDomToBytes(doc)
// logger.debug("response: $signedDoc")
return signedDoc
}
diff --git a/ebics/src/main/kotlin/ebics_h004/EbicsRequest.kt b/ebics/src/main/kotlin/ebics_h004/EbicsRequest.kt
index 263fb71a..2b89e963 100644
--- a/ebics/src/main/kotlin/ebics_h004/EbicsRequest.kt
+++ b/ebics/src/main/kotlin/ebics_h004/EbicsRequest.kt
@@ -286,11 +286,10 @@ class EbicsRequest {
}
companion object {
-
fun createForDownloadReceiptPhase(
- transactionId: String?,
- hostId: String
-
+ transactionId: String,
+ hostId: String,
+ success: Boolean
): EbicsRequest {
return EbicsRequest().apply {
header = Header().apply {
@@ -310,7 +309,7 @@ class EbicsRequest {
body = Body().apply {
transferReceipt = TransferReceipt().apply {
authenticate = true
- receiptCode = 0 // always true at this point.
+ receiptCode = if (success) 1 else 0
}
}
}
diff --git a/ebics/src/main/kotlin/ebics_h005/Ebics3Request.kt b/ebics/src/main/kotlin/ebics_h005/Ebics3Request.kt
index 54987c8b..ab710690 100644
--- a/ebics/src/main/kotlin/ebics_h005/Ebics3Request.kt
+++ b/ebics/src/main/kotlin/ebics_h005/Ebics3Request.kt
@@ -368,8 +368,9 @@ class Ebics3Request {
companion object {
fun createForDownloadReceiptPhase(
- transactionId: String?,
- hostId: String
+ transactionId: String,
+ hostId: String,
+ success: Boolean
): Ebics3Request {
return Ebics3Request().apply {
header = Header().apply {
@@ -389,7 +390,7 @@ class Ebics3Request {
body = Body().apply {
transferReceipt = TransferReceipt().apply {
authenticate = true
- receiptCode = 0 // always true at this point.
+ receiptCode = if (success) 1 else 0
}
}
}
diff --git a/ebics/src/test/kotlin/EbicsMessagesTest.kt b/ebics/src/test/kotlin/EbicsMessagesTest.kt
index 5d0f8f5d..2b8d63ca 100644
--- a/ebics/src/test/kotlin/EbicsMessagesTest.kt
+++ b/ebics/src/test/kotlin/EbicsMessagesTest.kt
@@ -17,8 +17,6 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.sandbox
-
import junit.framework.TestCase.assertEquals
import org.apache.xml.security.binding.xmldsig.SignatureType
import org.junit.Test
@@ -43,7 +41,7 @@ class EbicsMessagesTest {
fun testImportNonRoot() {
val classLoader = ClassLoader.getSystemClassLoader()
val ini = classLoader.getResource("ebics_ini_inner_key.xml")
- val jaxb = XMLUtil.convertStringToJaxb<SignatureTypes.SignaturePubKeyOrderData>(ini.readText())
+ val jaxb = XMLUtil.convertBytesToJaxb<SignatureTypes.SignaturePubKeyOrderData>(ini.readBytes())
assertEquals("A006", jaxb.value.signaturePubKeyInfo.signatureVersion)
}
@@ -54,7 +52,7 @@ class EbicsMessagesTest {
fun testStringToJaxb() {
val classLoader = ClassLoader.getSystemClassLoader()
val ini = classLoader.getResource("ebics_ini_request_sample.xml")
- val jaxb = XMLUtil.convertStringToJaxb<EbicsUnsecuredRequest>(ini.readText())
+ val jaxb = XMLUtil.convertBytesToJaxb<EbicsUnsecuredRequest>(ini.readBytes())
println("jaxb loaded")
assertEquals(
"INI",
@@ -74,7 +72,7 @@ class EbicsMessagesTest {
}
this.versionNumber = listOf(HEVResponse.VersionNumber.create("H004", "02.50"))
}
- XMLUtil.convertJaxbToString(hevResponseJaxb)
+ XMLUtil.convertJaxbToBytes(hevResponseJaxb)
}
/**
@@ -84,7 +82,7 @@ class EbicsMessagesTest {
fun testDomToJaxb() {
val classLoader = ClassLoader.getSystemClassLoader()
val ini = classLoader.getResource("ebics_ini_request_sample.xml")!!
- val iniDom = XMLUtil.parseStringIntoDom(ini.readText())
+ val iniDom = XMLUtil.parseBytesIntoDom(ini.readBytes())
XMLUtil.convertDomToJaxb<EbicsUnsecuredRequest>(
EbicsUnsecuredRequest::class.java,
iniDom
@@ -109,22 +107,22 @@ class EbicsMessagesTest {
}
}
}
- val text = XMLUtil.convertJaxbToString(responseXml)
- assertTrue(text.isNotEmpty())
+ val bytes = XMLUtil.convertJaxbToBytes(responseXml)
+ assertTrue(bytes.isNotEmpty())
}
@Test
fun testParseHiaRequestOrderData() {
val classLoader = ClassLoader.getSystemClassLoader()
- val hia = classLoader.getResource("hia_request_order_data.xml")!!.readText()
- XMLUtil.convertStringToJaxb<HIARequestOrderData>(hia)
+ val hia = classLoader.getResource("hia_request_order_data.xml")!!.readBytes()
+ XMLUtil.convertBytesToJaxb<HIARequestOrderData>(hia)
}
@Test
fun testHiaLoad() {
val classLoader = ClassLoader.getSystemClassLoader()
val hia = classLoader.getResource("hia_request.xml")!!
- val hiaDom = XMLUtil.parseStringIntoDom(hia.readText())
+ val hiaDom = XMLUtil.parseBytesIntoDom(hia.readBytes())
val x: Element = hiaDom.getElementsByTagNameNS(
"urn:org:ebics:H004",
"OrderDetails"
@@ -150,7 +148,7 @@ class EbicsMessagesTest {
"ebics_ini_inner_key.xml"
)
assertNotNull(file)
- XMLUtil.convertStringToJaxb<SignatureTypes.SignaturePubKeyOrderData>(file.readText())
+ XMLUtil.convertBytesToJaxb<SignatureTypes.SignaturePubKeyOrderData>(file.readBytes())
}
val modulus = jaxbKey.value.signaturePubKeyInfo.pubKeyValue.rsaKeyValue.modulus
@@ -161,8 +159,8 @@ class EbicsMessagesTest {
@Test
fun testLoadIniMessage() {
val classLoader = ClassLoader.getSystemClassLoader()
- val text = classLoader.getResource("ebics_ini_request_sample.xml")!!.readText()
- XMLUtil.convertStringToJaxb<EbicsUnsecuredRequest>(text)
+ val text = classLoader.getResource("ebics_ini_request_sample.xml")!!.readBytes()
+ XMLUtil.convertBytesToJaxb<EbicsUnsecuredRequest>(text)
}
@Test
@@ -185,14 +183,14 @@ class EbicsMessagesTest {
}
}
}
- print(XMLUtil.convertJaxbToString(response))
+ print(XMLUtil.convertJaxbToBytes(response).toString())
}
@Test
fun testLoadHpb() {
val classLoader = ClassLoader.getSystemClassLoader()
- val text = classLoader.getResource("hpb_request.xml")!!.readText()
- XMLUtil.convertStringToJaxb<EbicsNpkdRequest>(text)
+ val text = classLoader.getResource("hpb_request.xml")!!.readBytes()
+ XMLUtil.convertBytesToJaxb<EbicsNpkdRequest>(text)
}
@Test
@@ -248,9 +246,8 @@ class EbicsMessagesTest {
}
}
- val str = XMLUtil.convertJaxbToString(htd)
- println(str)
- assert(XMLUtil.validateFromString(str))
+ val bytes = XMLUtil.convertJaxbToBytes(htd)
+ assert(XMLUtil.validateFromBytes(bytes))
}
@@ -308,9 +305,8 @@ class EbicsMessagesTest {
})
}
- val str = XMLUtil.convertJaxbToString(hkd)
- println(str)
- assert(XMLUtil.validateFromString(str))
+ val bytes = XMLUtil.convertJaxbToBytes(hkd)
+ assert(XMLUtil.validateFromBytes(bytes))
}
@Test
@@ -361,11 +357,11 @@ class EbicsMessagesTest {
}
}
- val str = XMLUtil.convertJaxbToString(ebicsRequestObj)
- val doc = XMLUtil.parseStringIntoDom(str)
+ val str = XMLUtil.convertJaxbToBytes(ebicsRequestObj)
+ val doc = XMLUtil.parseBytesIntoDom(str)
val pair = CryptoUtil.generateRsaKeyPair(1024)
XMLUtil.signEbicsDocument(doc, pair.private)
- val finalStr = XMLUtil.convertDomToString(doc)
- assert(XMLUtil.validateFromString(finalStr))
+ val bytes = XMLUtil.convertDomToBytes(doc)
+ assert(XMLUtil.validateFromBytes(bytes))
}
} \ No newline at end of file
diff --git a/ebics/src/test/kotlin/EbicsOrderUtilTest.kt b/ebics/src/test/kotlin/EbicsOrderUtilTest.kt
index 05f7f72d..c78da738 100644
--- a/ebics/src/test/kotlin/EbicsOrderUtilTest.kt
+++ b/ebics/src/test/kotlin/EbicsOrderUtilTest.kt
@@ -302,7 +302,7 @@ class EbicsOrderUtilTest {
</Permission>
</UserInfo>
</HTDResponseOrderData>
- """.trimIndent()
- XMLUtil.convertStringToJaxb<HTDResponseOrderData>(orderDataXml);
+ """.trimIndent().toByteArray()
+ XMLUtil.convertBytesToJaxb<HTDResponseOrderData>(orderDataXml);
}
} \ No newline at end of file
diff --git a/ebics/src/test/kotlin/XmlUtilTest.kt b/ebics/src/test/kotlin/XmlUtilTest.kt
index b8639d7a..93ca8bf2 100644
--- a/ebics/src/test/kotlin/XmlUtilTest.kt
+++ b/ebics/src/test/kotlin/XmlUtilTest.kt
@@ -37,8 +37,7 @@ class XmlUtilTest {
@Test
fun deserializeConsecutiveLists() {
-
- val tmp = XMLUtil.convertStringToJaxb<HTDResponseOrderData>("""
+ val tmp = XMLUtil.convertBytesToJaxb<HTDResponseOrderData>("""
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<HTDResponseOrderData xmlns="urn:org:ebics:H004">
<PartnerInfo>
@@ -81,7 +80,7 @@ class XmlUtilTest {
<OrderTypes>C54 C53 C52 CCC</OrderTypes>
</Permission>
</UserInfo>
- </HTDResponseOrderData>""".trimIndent()
+ </HTDResponseOrderData>""".trimIndent().toByteArray()
)
println(tmp.value.partnerInfo.orderInfoList[0].description)
@@ -90,7 +89,7 @@ class XmlUtilTest {
@Test
fun exceptionOnConversion() {
try {
- XMLUtil.convertStringToJaxb<EbicsKeyManagementResponse>("<malformed xml>")
+ XMLUtil.convertBytesToJaxb<EbicsKeyManagementResponse>("<malformed xml>".toByteArray())
} catch (e: javax.xml.bind.UnmarshalException) {
// just ensuring this is the exception
println("caught")
@@ -115,12 +114,12 @@ class XmlUtilTest {
@Test
fun basicSigningTest() {
- val doc = XMLUtil.parseStringIntoDom("""
+ val doc = XMLUtil.parseBytesIntoDom("""
<myMessage xmlns:ebics="urn:org:ebics:H004">
<ebics:AuthSignature />
<foo authenticate="true">Hello World</foo>
</myMessage>
- """.trimIndent())
+ """.trimIndent().toByteArray())
val kpg = KeyPairGenerator.getInstance("RSA")
kpg.initialize(2048)
val pair = kpg.genKeyPair()
@@ -155,10 +154,9 @@ class XmlUtilTest {
}
val signature = signEbicsResponse(response, pair.private)
- val signatureJaxb = XMLUtil.convertStringToJaxb<EbicsResponse>(signature)
+ val signatureJaxb = XMLUtil.convertBytesToJaxb<EbicsResponse>(signature)
assertTrue(
-
XMLUtil.verifyEbicsDocument(
XMLUtil.convertJaxbToDocument(signatureJaxb.value),
pair.public
@@ -168,13 +166,13 @@ class XmlUtilTest {
@Test
fun multiAuthSigningTest() {
- val doc = XMLUtil.parseStringIntoDom("""
+ val doc = XMLUtil.parseBytesIntoDom("""
<myMessage xmlns:ebics="urn:org:ebics:H004">
<ebics:AuthSignature />
<foo authenticate="true">Hello World</foo>
<bar authenticate="true">Another one!</bar>
</myMessage>
- """.trimIndent())
+ """.trimIndent().toByteArray())
val kpg = KeyPairGenerator.getInstance("RSA")
kpg.initialize(2048)
val pair = kpg.genKeyPair()
@@ -185,8 +183,8 @@ class XmlUtilTest {
@Test
fun testRefSignature() {
val classLoader = ClassLoader.getSystemClassLoader()
- val docText = classLoader.getResourceAsStream("signature1/doc.xml")!!.readAllBytes().toString(Charsets.UTF_8)
- val doc = XMLUtil.parseStringIntoDom(docText)
+ val docText = classLoader.getResourceAsStream("signature1/doc.xml")!!.readAllBytes()
+ val doc = XMLUtil.parseBytesIntoDom(docText)
val keyText = classLoader.getResourceAsStream("signature1/public_key.txt")!!.readAllBytes()
val keyBytes = Base64.getDecoder().decode(keyText)
val key = CryptoUtil.loadRsaPublicKey(keyBytes)