diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4951d7c32..d4858414c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,9 +11,8 @@ Execute the following steps when bumping the Frank!Framework version: 4. Replace the default value for `FF_VERSION` under `services.zaakbrug.build.args` in `docker-compose.zaakbrug.dev.yml` with the new tag. NOTE: Watch out to not replace the '-' in front of the tag: ${FF_VERSION:-} 5. Replace the value of `ff.version` in `frank-runner.properties` with the new tag. 6. Start ZaakBrug with the `Frank!Runner` to automatically replace the `./src/main/configuration//FrankConfig.xsd` and `./src/main/configuration/FrankConfig.xsd` with the newer version. You can stop the Frank!Runner once the files are replaced. Note that currently the Frank!Runner will also add `FrankConfig.xsd` to the `.gitignore` file. Make sure to revert the change to `.gitignore`. -7. Check [GitHub - Frank!Framework - Parameter.java commit history](https://github.com/frankframework/frankframework/commits/master/core/src/main/java/org/frankframework/parameters/Parameter.java) for any changes to this class. The latest version of the source code of Parameter.java can be reached directly from master branch from [Github - Frank!Framework - Parameter.java source code](https://github.com/frankframework/frankframework/blob/master/core/src/main/java/org/frankframework/parameters/Parameter.java). If there are indeed changes, update the corresponding file under `./src/main/java/org/frankframework/...`. The `.java-orig` file content should be 1 on 1 equal to the new version on GitHub. Take care to not accidentally remove the intended customization of the code in the `.java` file. -8. Run the e2e testsuite by using the below Docker-Compose and configuration to validate the changes. You should only need `docker-compose -f ./docker-compose.zaakbrug.dev.yml -f ./docker-compose.openzaak.dev.yml up --build --force-recreate` for this. (TODO: Automate running of e2e tests in ci/cd). -9. Commit you changes on a branch with as message: `build(dependencies): bump f!f version to `. Create a PR to have you changes merged to master. +7. Run the e2e testsuite by using the below Docker-Compose and configuration to validate the changes. You should only need `docker-compose -f ./docker-compose.zaakbrug.dev.yml -f ./docker-compose.openzaak.dev.yml up --build --force-recreate` for this. (TODO: Automate running of e2e tests in ci/cd). +8. Commit you changes on a branch with as message: `build(dependencies): bump f!f version to `. Create a PR to have you changes merged to master. # Testing with SoapUI diff --git a/Dockerfile b/Dockerfile index df3a2a236..bc68382dc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,24 +7,22 @@ FROM docker.io/frankframework/frankframework:${FF_VERSION} as ff-base COPY --chown=tomcat lib/server/* /usr/local/tomcat/lib/ COPY --chown=tomcat lib/webapp/* /usr/local/tomcat/webapps/ROOT/WEB-INF/lib/ +# # Compile custom class +# FROM eclipse-temurin:17-jdk-jammy AS custom-code-builder -# Compile custom class -FROM eclipse-temurin:17-jdk-jammy AS custom-code-builder - -# Copy dependencies -COPY --from=ff-base /usr/local/tomcat/lib/ /usr/local/tomcat/lib/ -COPY --from=ff-base /usr/local/tomcat/webapps/ROOT /usr/local/tomcat/webapps/ROOT - -# Copy custom class -COPY src/main/java /tmp/java -RUN mkdir /tmp/classes && \ - javac \ - /tmp/java/org/frankframework/parameters/Parameter.java \ - -classpath "/usr/local/tomcat/webapps/ROOT/WEB-INF/lib/*:/usr/local/tomcat/lib/*" \ - -verbose -d /tmp/classes +# # Copy dependencies +# COPY --from=ff-base /usr/local/tomcat/lib/ /usr/local/tomcat/lib/ +# COPY --from=ff-base /usr/local/tomcat/webapps/ROOT /usr/local/tomcat/webapps/ROOT +# # Copy custom class +# COPY src/main/java /tmp/java +# RUN mkdir /tmp/classes && \ +# javac \ +# /tmp/java/org/frankframework/parameters/Parameter.java \ +# -classpath "/usr/local/tomcat/webapps/ROOT/WEB-INF/lib/*:/usr/local/tomcat/lib/*" \ +# -verbose -d /tmp/classes -FROM ff-base +# FROM ff-base # Copy custom entrypoint script with added options COPY --chown=tomcat docker/entrypoint.sh /scripts/entrypoint.sh @@ -45,8 +43,8 @@ COPY --chown=tomcat src/main/configurations/ /opt/frank/configurations/ COPY --chown=tomcat src/main/resources/ /opt/frank/resources/ COPY --chown=tomcat src/test/testtool/ /opt/frank/testtool/ -# Copy compiled custom class -COPY --from=custom-code-builder --chown=tomcat /tmp/classes/ /usr/local/tomcat/webapps/ROOT/WEB-INF/classes +# # Copy compiled custom class +# COPY --from=custom-code-builder --chown=tomcat /tmp/classes/ /usr/local/tomcat/webapps/ROOT/WEB-INF/classes # Check if Frank! is still healthy HEALTHCHECK --interval=15s --timeout=5s --start-period=30s --retries=60 \ diff --git a/src/main/configurations/Translate/Configuration.xml b/src/main/configurations/Translate/Configuration.xml index d188fd296..60b0cdc3b 100644 --- a/src/main/configurations/Translate/Configuration.xml +++ b/src/main/configurations/Translate/Configuration.xml @@ -15,14 +15,17 @@ + + + - - + + @@ -91,6 +94,9 @@ &GeefZaakdetails_Lv01; &GeefZaakdocumentbewerken_Di02; &GeefZaakdocumentLezen_Lv01; + &GenerateAuthorizationHeaderForCatalogiApi; + &GenerateAuthorizationHeaderForDocumentenApi; + &GenerateAuthorizationHeaderForZakenApi; &GenereerIdentificatieEmulator; &GetBas64Inhoud; &GetResultaatTypeByZaakTypeAndOmschrijving; diff --git a/src/main/configurations/Translate/Configuration_DeleteRolFromZgw.xml b/src/main/configurations/Translate/Configuration_DeleteRolFromZgw.xml index 80cb54daa..fb6ba81ea 100644 --- a/src/main/configurations/Translate/Configuration_DeleteRolFromZgw.xml +++ b/src/main/configurations/Translate/Configuration_DeleteRolFromZgw.xml @@ -14,20 +14,16 @@ - - - - - - + + + - + - - - - + - + diff --git a/src/main/configurations/Translate/Configuration_Documenten_PostZgwEnkelvoudigInformatieObject.xml b/src/main/configurations/Translate/Configuration_Documenten_PostZgwEnkelvoudigInformatieObject.xml index a4fc524ee..758e27e63 100644 --- a/src/main/configurations/Translate/Configuration_Documenten_PostZgwEnkelvoudigInformatieObject.xml +++ b/src/main/configurations/Translate/Configuration_Documenten_PostZgwEnkelvoudigInformatieObject.xml @@ -14,20 +14,16 @@ - - - - - - - - - + + + + + + - - - + diff --git a/src/main/configurations/Translate/Configuration_GenerateAuthorizationHeaderForCatalogiApi.xml b/src/main/configurations/Translate/Configuration_GenerateAuthorizationHeaderForCatalogiApi.xml new file mode 100644 index 000000000..3d0ac2dc5 --- /dev/null +++ b/src/main/configurations/Translate/Configuration_GenerateAuthorizationHeaderForCatalogiApi.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/configurations/Translate/Configuration_GenerateAuthorizationHeaderForDocumentenApi.xml b/src/main/configurations/Translate/Configuration_GenerateAuthorizationHeaderForDocumentenApi.xml new file mode 100644 index 000000000..bb397d4ea --- /dev/null +++ b/src/main/configurations/Translate/Configuration_GenerateAuthorizationHeaderForDocumentenApi.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/configurations/Translate/Configuration_GenerateAuthorizationHeaderForZakenApi.xml b/src/main/configurations/Translate/Configuration_GenerateAuthorizationHeaderForZakenApi.xml new file mode 100644 index 000000000..9a9bb6a73 --- /dev/null +++ b/src/main/configurations/Translate/Configuration_GenerateAuthorizationHeaderForZakenApi.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/configurations/Translate/Configuration_GetBas64Inhoud.xml b/src/main/configurations/Translate/Configuration_GetBas64Inhoud.xml index f36c2b9df..e18152ffe 100644 --- a/src/main/configurations/Translate/Configuration_GetBas64Inhoud.xml +++ b/src/main/configurations/Translate/Configuration_GetBas64Inhoud.xml @@ -18,20 +18,16 @@ - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_GetResultaatTypeByZaakTypeAndOmschrijving.xml b/src/main/configurations/Translate/Configuration_GetResultaatTypeByZaakTypeAndOmschrijving.xml index 9c8648f9e..ea8e0ed89 100644 --- a/src/main/configurations/Translate/Configuration_GetResultaatTypeByZaakTypeAndOmschrijving.xml +++ b/src/main/configurations/Translate/Configuration_GetResultaatTypeByZaakTypeAndOmschrijving.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -39,9 +35,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_GetResultatenByZaakUrl.xml b/src/main/configurations/Translate/Configuration_GetResultatenByZaakUrl.xml index 9a29045aa..14666bd4e 100644 --- a/src/main/configurations/Translate/Configuration_GetResultatenByZaakUrl.xml +++ b/src/main/configurations/Translate/Configuration_GetResultatenByZaakUrl.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -39,9 +35,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_GetRolByZaakUrlAndRolTypeUrl.xml b/src/main/configurations/Translate/Configuration_GetRolByZaakUrlAndRolTypeUrl.xml index 260961d97..6b349da80 100644 --- a/src/main/configurations/Translate/Configuration_GetRolByZaakUrlAndRolTypeUrl.xml +++ b/src/main/configurations/Translate/Configuration_GetRolByZaakUrlAndRolTypeUrl.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -47,9 +43,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_GetRolTypenByUrl.xml b/src/main/configurations/Translate/Configuration_GetRolTypenByUrl.xml index ebbd570a6..efd1ae995 100644 --- a/src/main/configurations/Translate/Configuration_GetRolTypenByUrl.xml +++ b/src/main/configurations/Translate/Configuration_GetRolTypenByUrl.xml @@ -10,20 +10,16 @@ - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_GetRollenByBsn.xml b/src/main/configurations/Translate/Configuration_GetRollenByBsn.xml index 6bae7fd0a..c5ccf3db6 100644 --- a/src/main/configurations/Translate/Configuration_GetRollenByBsn.xml +++ b/src/main/configurations/Translate/Configuration_GetRollenByBsn.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -39,9 +35,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_GetStatusTypes.xml b/src/main/configurations/Translate/Configuration_GetStatusTypes.xml index 96780f444..b09e5c5c2 100644 --- a/src/main/configurations/Translate/Configuration_GetStatusTypes.xml +++ b/src/main/configurations/Translate/Configuration_GetStatusTypes.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -39,9 +35,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZaakDocumentByUrl.xml b/src/main/configurations/Translate/Configuration_GetZaakDocumentByUrl.xml index 6df2df774..8db2a0158 100644 --- a/src/main/configurations/Translate/Configuration_GetZaakDocumentByUrl.xml +++ b/src/main/configurations/Translate/Configuration_GetZaakDocumentByUrl.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -38,9 +34,7 @@ /> - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZaakInformatieObjectenByZaak.xml b/src/main/configurations/Translate/Configuration_GetZaakInformatieObjectenByZaak.xml index f81f043a8..8e3d35442 100644 --- a/src/main/configurations/Translate/Configuration_GetZaakInformatieObjectenByZaak.xml +++ b/src/main/configurations/Translate/Configuration_GetZaakInformatieObjectenByZaak.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -39,9 +35,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZaakTypeByUrl.xml b/src/main/configurations/Translate/Configuration_GetZaakTypeByUrl.xml index ee3ab73f9..d52944599 100644 --- a/src/main/configurations/Translate/Configuration_GetZaakTypeByUrl.xml +++ b/src/main/configurations/Translate/Configuration_GetZaakTypeByUrl.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -38,9 +34,7 @@ /> - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZgwEnkelvoudigInformatieObjectByIdentificatie.xml b/src/main/configurations/Translate/Configuration_GetZgwEnkelvoudigInformatieObjectByIdentificatie.xml index 643ce7ace..96cc92b05 100644 --- a/src/main/configurations/Translate/Configuration_GetZgwEnkelvoudigInformatieObjectByIdentificatie.xml +++ b/src/main/configurations/Translate/Configuration_GetZgwEnkelvoudigInformatieObjectByIdentificatie.xml @@ -18,24 +18,20 @@ xpathExpression="string-length($Identificatie) > 0" > - + - - - - - - + + + - + @@ -48,9 +44,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZgwInformatieObjectTypeByUrl.xml b/src/main/configurations/Translate/Configuration_GetZgwInformatieObjectTypeByUrl.xml index e53364673..59eabf772 100644 --- a/src/main/configurations/Translate/Configuration_GetZgwInformatieObjectTypeByUrl.xml +++ b/src/main/configurations/Translate/Configuration_GetZgwInformatieObjectTypeByUrl.xml @@ -14,20 +14,16 @@ - - - - - - + + + - + @@ -39,9 +35,7 @@ /> - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZgwInformatieObjectUnlock.xml b/src/main/configurations/Translate/Configuration_GetZgwInformatieObjectUnlock.xml index e6f6c385f..e675b4d48 100644 --- a/src/main/configurations/Translate/Configuration_GetZgwInformatieObjectUnlock.xml +++ b/src/main/configurations/Translate/Configuration_GetZgwInformatieObjectUnlock.xml @@ -14,20 +14,16 @@ - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZgwRolesByZaakUrl.xml b/src/main/configurations/Translate/Configuration_GetZgwRolesByZaakUrl.xml index 636473c57..e91d21a32 100644 --- a/src/main/configurations/Translate/Configuration_GetZgwRolesByZaakUrl.xml +++ b/src/main/configurations/Translate/Configuration_GetZgwRolesByZaakUrl.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -39,9 +35,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZgwStatusTypeByUrl.xml b/src/main/configurations/Translate/Configuration_GetZgwStatusTypeByUrl.xml index 898a50958..478e97812 100644 --- a/src/main/configurations/Translate/Configuration_GetZgwStatusTypeByUrl.xml +++ b/src/main/configurations/Translate/Configuration_GetZgwStatusTypeByUrl.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -38,9 +34,7 @@ /> - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZgwZaak.xml b/src/main/configurations/Translate/Configuration_GetZgwZaak.xml index bb09da2f5..3d606980f 100644 --- a/src/main/configurations/Translate/Configuration_GetZgwZaak.xml +++ b/src/main/configurations/Translate/Configuration_GetZgwZaak.xml @@ -17,24 +17,20 @@ xpathExpression="string-length($Identificatie) > 0 and $Identificatie != 'null'" > - + - - - - - - + + + - + @@ -47,9 +43,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZgwZaakByUrl.xml b/src/main/configurations/Translate/Configuration_GetZgwZaakByUrl.xml index 3f0cb8b11..b7230e4c4 100644 --- a/src/main/configurations/Translate/Configuration_GetZgwZaakByUrl.xml +++ b/src/main/configurations/Translate/Configuration_GetZgwZaakByUrl.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -38,9 +34,7 @@ /> - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZgwZaakInformatieObjectByEnkelvoudigInformatieObjectUrl.xml b/src/main/configurations/Translate/Configuration_GetZgwZaakInformatieObjectByEnkelvoudigInformatieObjectUrl.xml index e1294e70a..6b38eb9d5 100644 --- a/src/main/configurations/Translate/Configuration_GetZgwZaakInformatieObjectByEnkelvoudigInformatieObjectUrl.xml +++ b/src/main/configurations/Translate/Configuration_GetZgwZaakInformatieObjectByEnkelvoudigInformatieObjectUrl.xml @@ -14,20 +14,16 @@ - - - - - - + + + - + @@ -40,9 +36,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_GetZgwZaakTypeByIdentificatie.xml b/src/main/configurations/Translate/Configuration_GetZgwZaakTypeByIdentificatie.xml index 15637c162..0d90fd5d2 100644 --- a/src/main/configurations/Translate/Configuration_GetZgwZaakTypeByIdentificatie.xml +++ b/src/main/configurations/Translate/Configuration_GetZgwZaakTypeByIdentificatie.xml @@ -14,20 +14,16 @@ - - - - - - + + + - + @@ -41,9 +37,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_PatchRelevanteAndereZaak.xml b/src/main/configurations/Translate/Configuration_PatchRelevanteAndereZaak.xml index 428f76058..b8e19b3d4 100644 --- a/src/main/configurations/Translate/Configuration_PatchRelevanteAndereZaak.xml +++ b/src/main/configurations/Translate/Configuration_PatchRelevanteAndereZaak.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_PostResultaat.xml b/src/main/configurations/Translate/Configuration_PostResultaat.xml index 0c1fe0c83..2fefe9b32 100644 --- a/src/main/configurations/Translate/Configuration_PostResultaat.xml +++ b/src/main/configurations/Translate/Configuration_PostResultaat.xml @@ -14,20 +14,16 @@ - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_PostZaak.xml b/src/main/configurations/Translate/Configuration_PostZaak.xml index b11f38f79..c91cc07ae 100644 --- a/src/main/configurations/Translate/Configuration_PostZaak.xml +++ b/src/main/configurations/Translate/Configuration_PostZaak.xml @@ -33,20 +33,16 @@ --> - - - - - - + + + - + @@ -67,9 +63,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_PostZgwLock.xml b/src/main/configurations/Translate/Configuration_PostZgwLock.xml index 5ca75ba15..d3e11cf86 100644 --- a/src/main/configurations/Translate/Configuration_PostZgwLock.xml +++ b/src/main/configurations/Translate/Configuration_PostZgwLock.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -43,9 +39,7 @@ /> - - - + diff --git a/src/main/configurations/Translate/Configuration_PutZgwZaakDocument.xml b/src/main/configurations/Translate/Configuration_PutZgwZaakDocument.xml index fc53bedf9..517f0d369 100644 --- a/src/main/configurations/Translate/Configuration_PutZgwZaakDocument.xml +++ b/src/main/configurations/Translate/Configuration_PutZgwZaakDocument.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_SetResultaatAndStatus.xml b/src/main/configurations/Translate/Configuration_SetResultaatAndStatus.xml index 08df41221..dd3852724 100644 --- a/src/main/configurations/Translate/Configuration_SetResultaatAndStatus.xml +++ b/src/main/configurations/Translate/Configuration_SetResultaatAndStatus.xml @@ -125,24 +125,20 @@ returnedSessionKeys="Error"> - + - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_Zaken_DeleteZgwZaak.xml b/src/main/configurations/Translate/Configuration_Zaken_DeleteZgwZaak.xml index 9d22f2bbc..9aebe7cb8 100644 --- a/src/main/configurations/Translate/Configuration_Zaken_DeleteZgwZaak.xml +++ b/src/main/configurations/Translate/Configuration_Zaken_DeleteZgwZaak.xml @@ -13,19 +13,16 @@ - - - - - - + + + - + + - - - + diff --git a/src/main/configurations/Translate/Configuration_Zaken_GetZgwRolTypeByUrl.xml b/src/main/configurations/Translate/Configuration_Zaken_GetZgwRolTypeByUrl.xml index f0ea76012..49fa3f360 100644 --- a/src/main/configurations/Translate/Configuration_Zaken_GetZgwRolTypeByUrl.xml +++ b/src/main/configurations/Translate/Configuration_Zaken_GetZgwRolTypeByUrl.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_Zaken_GetZgwRolTypeByZaakType.xml b/src/main/configurations/Translate/Configuration_Zaken_GetZgwRolTypeByZaakType.xml index 3203c19c3..71a4fbd40 100644 --- a/src/main/configurations/Translate/Configuration_Zaken_GetZgwRolTypeByZaakType.xml +++ b/src/main/configurations/Translate/Configuration_Zaken_GetZgwRolTypeByZaakType.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_Zaken_GetZgwStatusByZaakUrl.xml b/src/main/configurations/Translate/Configuration_Zaken_GetZgwStatusByZaakUrl.xml index f5adfaedd..d05169a4c 100644 --- a/src/main/configurations/Translate/Configuration_Zaken_GetZgwStatusByZaakUrl.xml +++ b/src/main/configurations/Translate/Configuration_Zaken_GetZgwStatusByZaakUrl.xml @@ -13,20 +13,16 @@ - - - - - - + + + - + @@ -39,9 +35,7 @@ - - - + diff --git a/src/main/configurations/Translate/Configuration_Zaken_PostZgwRol.xml b/src/main/configurations/Translate/Configuration_Zaken_PostZgwRol.xml index d8b29ae0f..42ba7be96 100644 --- a/src/main/configurations/Translate/Configuration_Zaken_PostZgwRol.xml +++ b/src/main/configurations/Translate/Configuration_Zaken_PostZgwRol.xml @@ -12,20 +12,16 @@ - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_Zaken_PostZgwStatus.xml b/src/main/configurations/Translate/Configuration_Zaken_PostZgwStatus.xml index 007a44497..d10740ecc 100644 --- a/src/main/configurations/Translate/Configuration_Zaken_PostZgwStatus.xml +++ b/src/main/configurations/Translate/Configuration_Zaken_PostZgwStatus.xml @@ -16,7 +16,7 @@ deepSearch="true" throwException="true" storeResultInSessionKey="inputForPostZgwStatus"> - + @@ -24,20 +24,16 @@ - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_Zaken_PostZgwZaakInformatieObject.xml b/src/main/configurations/Translate/Configuration_Zaken_PostZgwZaakInformatieObject.xml index e8d79faf4..bdd470f13 100644 --- a/src/main/configurations/Translate/Configuration_Zaken_PostZgwZaakInformatieObject.xml +++ b/src/main/configurations/Translate/Configuration_Zaken_PostZgwZaakInformatieObject.xml @@ -15,20 +15,16 @@ - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/Configuration_Zaken_UpdateZgwZaak.xml b/src/main/configurations/Translate/Configuration_Zaken_UpdateZgwZaak.xml index 82ba0a6a0..8ec3ca0a7 100644 --- a/src/main/configurations/Translate/Configuration_Zaken_UpdateZgwZaak.xml +++ b/src/main/configurations/Translate/Configuration_Zaken_UpdateZgwZaak.xml @@ -21,23 +21,19 @@ compactJsonArrays="false" storeResultInSessionKey="storeInput" throwException="true"> - + - - - - - - + + + - + - - - + diff --git a/src/main/configurations/Translate/DeploymentSpecifics.properties b/src/main/configurations/Translate/DeploymentSpecifics.properties index db01e5170..817e731ee 100644 --- a/src/main/configurations/Translate/DeploymentSpecifics.properties +++ b/src/main/configurations/Translate/DeploymentSpecifics.properties @@ -24,6 +24,9 @@ GeefLijstZaakdocumenten_Lv01.Active=true GeefZaakdetails_Lv01.Active=true GeefZaakdocumentbewerken_Di02.Active=true GeefZaakdocumentLezen_Lv01.Active=true +GenerateAuthorizationHeaderForCatalogiApi.Active=true +GenerateAuthorizationHeaderForDocumentenApi.Active=true +GenerateAuthorizationHeaderForZakenApi.Active=true GenereerIdentificatieEmulator.Active=true GetBas64Inhoud.Active=true GetZgwResultaatTypeByZaakTypeAndOmschrijving.Active=true diff --git a/src/main/java/org/frankframework/parameters/Parameter.java b/src/main/java/org/frankframework/parameters/Parameter.java deleted file mode 100644 index fa200883a..000000000 --- a/src/main/java/org/frankframework/parameters/Parameter.java +++ /dev/null @@ -1,1189 +0,0 @@ -/* - Copyright 2013, 2016, 2019, 2020 Nationale-Nederlanden, 2021-2023 WeAreFrank! - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -package org.frankframework.parameters; - -import static org.frankframework.functional.FunctionalUtil.logValue; -import static org.frankframework.util.StringUtil.hide; - -import java.io.IOException; -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.MessageFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.time.ZoneOffset; -import java.util.ArrayList; -import java.util.Base64; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.StringTokenizer; - -import javax.xml.transform.Source; -import javax.xml.transform.TransformerException; -import javax.xml.transform.dom.DOMResult; - -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.frankframework.configuration.ConfigurationException; -import org.frankframework.configuration.ConfigurationUtils; -import org.frankframework.configuration.ConfigurationWarning; -import org.frankframework.core.IConfigurable; -import org.frankframework.core.IWithParameters; -import org.frankframework.core.ParameterException; -import org.frankframework.core.PipeLineSession; -import org.frankframework.doc.DocumentedEnum; -import org.frankframework.doc.EnumLabel; -import org.frankframework.jdbc.StoredProcedureQuerySender; -import org.frankframework.pipes.PutSystemDateInSession; -import org.frankframework.stream.Message; -import org.frankframework.util.AppConstants; -import org.frankframework.util.CredentialFactory; -import org.frankframework.util.DateFormatUtils; -import org.frankframework.util.DomBuilderException; -import org.frankframework.util.EnumUtils; -import org.frankframework.util.Misc; -import org.frankframework.util.StringUtil; -import org.frankframework.util.TransformerPool; -import org.frankframework.util.TransformerPool.OutputType; -import org.frankframework.util.UUIDUtil; -import org.frankframework.util.XmlBuilder; -import org.frankframework.util.XmlException; -import org.frankframework.util.XmlUtils; -import org.springframework.context.ApplicationContext; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import io.fusionauth.jwt.Signer; -import io.fusionauth.jwt.hmac.HMACSigner; -import lombok.Getter; -import lombok.Setter; - -import static java.time.ZonedDateTime.now; - -/** - * Generic parameter definition. - * - * A parameter resembles an attribute. However, while attributes get their value at configuration-time, - * parameters get their value at the time of processing the message. Value can be retrieved from the message itself, - * a fixed value, or from the pipelineSession. If this does not result in a value (or if neither of these is specified), a default value - * can be specified. If an XPathExpression or stylesheet is specified, it will be applied to the message, the value retrieved - * from the pipelineSession or the fixed value specified. If the transformation produces no output, the default value - * of the parameter is taken if provided. - *

- * Examples: - *

- * stored under SessionKey 'TransportInfo':
- *  <transportinfo>
- *   <to>***@zonnet.nl</to>
- *   <to>***@zonnet.nl</to>
- *   <cc>***@zonnet.nl</cc>
- *  </transportinfo>
- *
- * to obtain all 'to' addressees as a parameter:
- * sessionKey="TransportInfo"
- * xpathExpression="transportinfo/to"
- * type="xml"
- *
- * Result:
- *   <to>***@zonnet.nl</to>
- *   <to>***@zonnet.nl</to>
- * 
- * - * N.B. to obtain a fixed value: a non-existing 'dummy' sessionKey in combination with the fixed value in defaultValue is used traditionally. - * The current version of parameter supports the 'value' attribute, that is sufficient to set a fixed value. - * @author Gerrit van Brakel - * @ff.parameters Parameters themselves can have parameters too, for instance if a XSLT transformation is used, that transformation can have parameters. - */ -public class Parameter implements IConfigurable, IWithParameters { - private static final Logger LOG = LogManager.getLogger(Parameter.class); - private final @Getter ClassLoader configurationClassLoader = Thread.currentThread().getContextClassLoader(); - private @Getter @Setter ApplicationContext applicationContext; - - public static final String TYPE_DATE_PATTERN="yyyy-MM-dd"; - public static final String TYPE_TIME_PATTERN="HH:mm:ss"; - public static final String TYPE_DATETIME_PATTERN="yyyy-MM-dd HH:mm:ss"; - public static final String TYPE_TIMESTAMP_PATTERN= DateFormatUtils.FORMAT_FULL_GENERIC; - - public static final String FIXEDUID ="0a1b234c--56de7fa8_9012345678b_-9cd0"; - public static final String FIXEDHOSTNAME ="MYHOST000012345"; - - private String name = null; - private @Getter ParameterType type = ParameterType.STRING; - private @Getter String sessionKey = null; - private @Getter String sessionKeyXPath = null; - private @Getter String contextKey = null; - private @Getter String xpathExpression = null; - private @Getter String namespaceDefs = null; - private @Getter String styleSheetName = null; - private @Getter String pattern = null; - private @Getter String authAlias; - private @Getter String username; - private @Getter String password; - private @Getter boolean ignoreUnresolvablePatternElements = false; - private @Getter String defaultValue = null; - private @Getter String defaultValueMethods = "defaultValue"; - private @Getter String value = null; - private @Getter String formatString = null; - private @Getter String decimalSeparator = null; - private @Getter String groupingSeparator = null; - private @Getter int minLength = -1; - private @Getter int maxLength = -1; - private @Getter String minInclusiveString = null; - private @Getter String maxInclusiveString = null; - private Number minInclusive; - private Number maxInclusive; - private @Getter boolean hidden = false; - private @Getter boolean removeNamespaces=false; - private @Getter int xsltVersion = 0; // set to 0 for auto-detect. - - private @Getter DecimalFormatSymbols decimalFormatSymbols = null; - private TransformerPool transformerPool = null; - private TransformerPool tpDynamicSessionKey = null; - protected ParameterList paramList = null; - private boolean configured = false; - private CredentialFactory cf; - - private List defaultValueMethodsList; - - @Getter - private ParameterMode mode = ParameterMode.INPUT; - - public enum ParameterMode { - INPUT, OUTPUT, INOUT - } - - public enum ParameterType { - /** Renders the contents of the first node (in combination with xslt or xpath). Please note that - * if there are child nodes, only the contents are returned, use XML if the xml tags are required */ - STRING, - - /** Renders an xml-nodeset as an xml-string (in combination with xslt or xpath). This will include the xml tags */ - XML, - - /** Renders the CONTENTS of the first node as a nodeset - * that can be used as such when passed as xslt-parameter (only for XSLT 1.0). - * Please note that the nodeset may contain multiple nodes, without a common root node. - * N.B. The result is the set of children of what you might expect it to be... */ - NODE(true), - - /** Renders XML as a DOM document; similar to node - with the distinction that there is always a common root node (required for XSLT 2.0) */ - DOMDOC(true), - - /** Converts the result to a Date, by default using formatString yyyy-MM-dd. - * When applied as a JDBC parameter, the method setDate() is used */ - DATE(true), - - /** Converts the result to a Date, by default using formatString HH:mm:ss. - * When applied as a JDBC parameter, the method setTime() is used */ - TIME(true), - - /** Converts the result to a Date, by default using formatString yyyy-MM-dd HH:mm:ss. - * When applied as a JDBC parameter, the method setTimestamp() is used */ - DATETIME(true), - - /** Similar to DATETIME, except for the formatString that is yyyy-MM-dd HH:mm:ss.SSS by default */ - TIMESTAMP(true), - - /** Converts the result from a XML formatted dateTime to a Date. - * When applied as a JDBC parameter, the method setTimestamp() is used */ - XMLDATETIME(true), - - /** Converts the result to a Number, using decimalSeparator and groupingSeparator. - * When applied as a JDBC parameter, the method setDouble() is used */ - NUMBER(true), - - /** Converts the result to an Integer */ - INTEGER(true), - - /** Converts the result to a Boolean */ - BOOLEAN(true), - - /** Only applicable as a JDBC parameter, the method setBinaryStream() is used */ - @ConfigurationWarning("use type [BINARY] instead") - @Deprecated INPUTSTREAM, - - /** Only applicable as a JDBC parameter, the method setBytes() is used */ - @ConfigurationWarning("use type [BINARY] instead") - @Deprecated BYTES, - - /** Forces the parameter value to be treated as binary data (e.g. when using a SQL BLOB field). - * When applied as a JDBC parameter, the method setBinaryStream() or setBytes() is used */ - BINARY, - - /** Forces the parameter value to be treated as character data (e.g. when using a SQL CLOB field). - * When applied as a JDBC parameter, the method setCharacterStream() or setString() is used */ - CHARACTER, - - /** - * Used for StoredProcedure OUT parameters when the database type is a {@code CURSOR} or {@link java.sql.JDBCType#REF_CURSOR}. - * See also {@link org.frankframework.jdbc.StoredProcedureQuerySender}. - *
- * DEPRECATED: Type LIST can also be used in larva test to Convert a List to an xml-string (<items><item>...</item><item>...</item></items>) */ - LIST, - - /** (Used in larva only) Converts a Map<String, String> object to a xml-string (<items><item name='...'>...</item><item name='...'>...</item></items>) */ - @Deprecated MAP; - - public final boolean requiresTypeConversion; - - private ParameterType() { - this(false); - } - - private ParameterType(boolean requiresTypeConverion) { - this.requiresTypeConversion = requiresTypeConverion; - } - - } - - public enum DefaultValueMethods implements DocumentedEnum { - @EnumLabel("defaultValue") DEFAULTVALUE, - @EnumLabel("sessionKey") SESSIONKEY, - @EnumLabel("pattern") PATTERN, - @EnumLabel("value") VALUE, - @EnumLabel("input") INPUT; - } - - public Parameter() { - super(); - } - - /** utility constructor, useful for unit testing */ - public Parameter(String name, String value) { - this(); - this.name = name; - this.value = value; - } - - @Override - public void addParameter(Parameter p) { - if (paramList==null) { - paramList=new ParameterList(); - } - paramList.add(p); - } - - @Override - public ParameterList getParameterList() { - return paramList; - } - - @Override - public void configure() throws ConfigurationException { - if (StringUtils.isNotEmpty(getSessionKey()) && StringUtils.isNotEmpty(getSessionKeyXPath())) { - throw new ConfigurationException("Parameter ["+getName()+"] cannot have both sessionKey and sessionKeyXPath specified"); - } - if (StringUtils.isNotEmpty(getXpathExpression()) || StringUtils.isNotEmpty(styleSheetName)) { - if (paramList!=null) { - paramList.configure(); - } - OutputType outputType = getType() == ParameterType.XML || getType() == ParameterType.NODE || getType() == ParameterType.DOMDOC ? OutputType.XML : OutputType.TEXT; - boolean includeXmlDeclaration = false; - - transformerPool = TransformerPool.configureTransformer0(this, getNamespaceDefs(), getXpathExpression(), getStyleSheetName(), outputType, includeXmlDeclaration, paramList, getXsltVersion()); - } else { - if (paramList != null && StringUtils.isEmpty(getPattern())) { - throw new ConfigurationException("Parameter [" + getName() + "] can only have parameters itself if a styleSheetName, xpathExpression or pattern is specified"); - } - } - if (StringUtils.isNotEmpty(getSessionKeyXPath())) { - tpDynamicSessionKey = TransformerPool.configureTransformer(this, getNamespaceDefs(), getSessionKeyXPath(), null, OutputType.TEXT,false,null); - } - if (getType() == null) { - LOG.info("parameter [{} has no type. Setting the type to [{}]", this::getType, ()->ParameterType.STRING); - setType(ParameterType.STRING); - } - if(StringUtils.isEmpty(getFormatString())) { - switch(getType()) { - case DATE: - setFormatString(TYPE_DATE_PATTERN); - break; - case DATETIME: - setFormatString(TYPE_DATETIME_PATTERN); - break; - case TIMESTAMP: - setFormatString(TYPE_TIMESTAMP_PATTERN); - break; - case TIME: - setFormatString(TYPE_TIME_PATTERN); - break; - default: - break; - } - } - if (getType()==ParameterType.NUMBER) { - decimalFormatSymbols = new DecimalFormatSymbols(); - if (StringUtils.isNotEmpty(getDecimalSeparator())) { - decimalFormatSymbols.setDecimalSeparator(getDecimalSeparator().charAt(0)); - } - if (StringUtils.isNotEmpty(getGroupingSeparator())) { - decimalFormatSymbols.setGroupingSeparator(getGroupingSeparator().charAt(0)); - } - } - configured = true; - - if (getMinInclusiveString()!=null || getMaxInclusiveString()!=null) { - if (getType()!=ParameterType.NUMBER) { - throw new ConfigurationException("minInclusive and maxInclusive only allowed in combination with type ["+ParameterType.NUMBER+"]"); - } - if (getMinInclusiveString()!=null) { - DecimalFormat df = new DecimalFormat(); - df.setDecimalFormatSymbols(decimalFormatSymbols); - try { - minInclusive = df.parse(getMinInclusiveString()); - } catch (ParseException e) { - throw new ConfigurationException("Attribute [minInclusive] could not parse result ["+getMinInclusiveString()+"] to number; decimalSeparator ["+decimalFormatSymbols.getDecimalSeparator()+"] groupingSeparator ["+decimalFormatSymbols.getGroupingSeparator()+"]",e); - } - } - if (getMaxInclusiveString()!=null) { - DecimalFormat df = new DecimalFormat(); - df.setDecimalFormatSymbols(decimalFormatSymbols); - try { - maxInclusive = df.parse(getMaxInclusiveString()); - } catch (ParseException e) { - throw new ConfigurationException("Attribute [maxInclusive] could not parse result ["+getMaxInclusiveString()+"] to number; decimalSeparator ["+decimalFormatSymbols.getDecimalSeparator()+"] groupingSeparator ["+decimalFormatSymbols.getGroupingSeparator()+"]",e); - } - } - } - if (StringUtils.isNotEmpty(getAuthAlias()) || StringUtils.isNotEmpty(getUsername()) || StringUtils.isNotEmpty(getPassword())) { - cf=new CredentialFactory(getAuthAlias(), getUsername(), getPassword()); - } - } - - private List getDefaultValueMethodsList() { - if (defaultValueMethodsList == null) { - defaultValueMethodsList = StringUtil.splitToStream(getDefaultValueMethods(), ", ") - .map(token -> EnumUtils.parse(DefaultValueMethods.class, token)) - .collect(Collectors.toList()); - } - return defaultValueMethodsList; - } - - private Document transformToDocument(Source xmlSource, ParameterValueList pvl) throws TransformerException, IOException { - TransformerPool pool = getTransformerPool(); - DOMResult transformResult = new DOMResult(); - pool.transform(xmlSource,transformResult, pvl); - return (Document) transformResult.getNode(); - } - - public boolean isWildcardSessionKey() { - return "*".equals(getSessionKey()); - } - /** - * if this returns true, then the input value must be repeatable, as it might be used multiple times. - */ - public boolean requiresInputValueForResolution() { - if (tpDynamicSessionKey != null) { // tpDynamicSessionKey is applied to the input message to retrieve the session key - return true; - } - return StringUtils.isEmpty(getContextKey()) && - (StringUtils.isEmpty(getSessionKey()) && StringUtils.isEmpty(getValue()) && StringUtils.isEmpty(getPattern()) - || getDefaultValueMethodsList().contains(DefaultValueMethods.INPUT) - ); - } - - public boolean requiresInputValueOrContextForResolution() { - if (tpDynamicSessionKey != null) { // tpDynamicSessionKey is applied to the input message to retrieve the session key - return true; - } - return StringUtils.isEmpty(getSessionKey()) && StringUtils.isEmpty(getValue()) && StringUtils.isEmpty(getPattern()) - || getDefaultValueMethodsList().contains(DefaultValueMethods.INPUT); - } - - public boolean consumesSessionVariable(String sessionKey) { - return StringUtils.isEmpty(getContextKey()) && ( - sessionKey.equals(getSessionKey()) - || getPattern()!=null && getPattern().contains("{"+sessionKey+"}") - || getParameterList()!=null && getParameterList().consumesSessionVariable(sessionKey) - ); - } - - /** - * determines the raw value - */ - public Object getValue(ParameterValueList alreadyResolvedParameters, Message message, PipeLineSession session, boolean namespaceAware) throws ParameterException { - Object result = null; - LOG.debug("Calculating value for Parameter [{}]", this::getName); - if (!configured) { - throw new ParameterException(getName(), "Parameter ["+getName()+"] not configured"); - } - - String requestedSessionKey; - if (tpDynamicSessionKey != null) { - try { - requestedSessionKey = tpDynamicSessionKey.transform(message.asSource()); - } catch (Exception e) { - throw new ParameterException(getName(), "SessionKey for parameter ["+getName()+"] exception on transformation to get name", e); - } - } else { - requestedSessionKey = getSessionKey(); - } - TransformerPool pool = getTransformerPool(); - if (pool != null) { - try { - /* - * determine source for XSLT transformation from - * 1) value attribute - * 2) requestedSessionKey - * 3) pattern - * 4) input message - * - * N.B. this order differs from untransformed parameters - */ - Source source; - if (getValue() != null) { - source = XmlUtils.stringToSourceForSingleUse(getValue(), namespaceAware); - } else if (StringUtils.isNotEmpty(requestedSessionKey)) { - Object sourceObject = session.get(requestedSessionKey); - if (getType() == ParameterType.LIST && sourceObject instanceof List) { - // larva can produce the sourceObject as list - List items = (List) sourceObject; - XmlBuilder itemsXml = new XmlBuilder("items"); - for (String item : items) { - XmlBuilder itemXml = new XmlBuilder("item"); - itemXml.setValue(item); - itemsXml.addSubElement(itemXml); - } - source = XmlUtils.stringToSourceForSingleUse(itemsXml.toXML(), namespaceAware); - } else if (getType() == ParameterType.MAP && sourceObject instanceof Map) { - // larva can produce the sourceObject as map - Map items = (Map) sourceObject; - XmlBuilder itemsXml = new XmlBuilder("items"); - for (String item : items.keySet()) { - XmlBuilder itemXml = new XmlBuilder("item"); - itemXml.addAttribute("name", item); - itemXml.setValue(items.get(item)); - itemsXml.addSubElement(itemXml); - } - source = XmlUtils.stringToSourceForSingleUse(itemsXml.toXML(), namespaceAware); - } else { - Message sourceMsg = Message.asMessage(sourceObject); - if (StringUtils.isNotEmpty(getContextKey())) { - sourceMsg = Message.asMessage(sourceMsg.getContext().get(getContextKey())); - } - if (!sourceMsg.isEmpty()) { - LOG.debug("Parameter [{}] using sessionvariable [{}] as source for transformation", this::getName, () -> requestedSessionKey); - source = sourceMsg.asSource(); - } else { - LOG.debug("Parameter [{}] sessionvariable [{}] empty, no transformation will be performed", this::getName, () -> requestedSessionKey); - source = null; - } - } - } else if (StringUtils.isNotEmpty(getPattern())) { - String sourceString = formatPattern(alreadyResolvedParameters, session); - if (StringUtils.isNotEmpty(sourceString)) { - LOG.debug("Parameter [{}] using pattern [{}] as source for transformation", this::getName, this::getPattern); - source = XmlUtils.stringToSourceForSingleUse(sourceString, namespaceAware); - } else { - LOG.debug("Parameter [{}] pattern [{}] empty, no transformation will be performed", this::getName, this::getPattern); - source = null; - } - } else if (message != null) { - if (StringUtils.isNotEmpty(getContextKey())) { - source = Message.asMessage(message.getContext().get(getContextKey())).asSource(); - } else { - source = message.asSource(); - } - } else { - source = null; - } - if (source!=null) { - if (isRemoveNamespaces()) { - // TODO: There should be a more efficient way to do this - String rnResult = XmlUtils.removeNamespaces(XmlUtils.source2String(source)); - source = XmlUtils.stringToSource(rnResult); - } - ParameterValueList pvl = paramList == null ? null : paramList.getValues(message, session, namespaceAware); - switch (getType()) { - case NODE: - return transformToDocument(source, pvl).getFirstChild(); - case DOMDOC: - return transformToDocument(source, pvl); - default: - String transformResult = pool.transform(source, pvl); - if (StringUtils.isNotEmpty(transformResult)) { - result = transformResult; - } - break; - } - } - } catch (Exception e) { - throw new ParameterException(getName(), "Parameter ["+getName()+"] exception on transformation to get parametervalue", e); - } - } else { - /* - * No XSLT transformation, determine primary result from - * 1) requestedSessionKey - * 2) pattern - * 3) value attribute - * 4) input message - * - * N.B. this order differs from transformed parameters. - */ - if (StringUtils.isNotEmpty(requestedSessionKey)) { - result = session.get(requestedSessionKey); - if (result instanceof Message && StringUtils.isNotEmpty(getContextKey())) { - result = ((Message)result).getContext().get(getContextKey()); - } - if (LOG.isDebugEnabled() && (result == null || - ((result instanceof String) && ((String) result).isEmpty()) || - ((result instanceof Message) && ((Message) result).isEmpty()))) { - LOG.debug("Parameter [{}] session variable [{}] is empty", this::getName, () -> requestedSessionKey); - } - } else if (StringUtils.isNotEmpty(getPattern())) { - result = formatPattern(alreadyResolvedParameters, session); - } else if (getValue()!=null) { - result = getValue(); - String strResult = result.toString(); - if ("Authorization".equals(getName()) && result != null && strResult.endsWith(".jwt@@")) { - // E.g. with the property JwtToken is - // is already resolved at this point (being an empty string when property JwtToken isn't found) - - AppConstants appConstants = AppConstants.getInstance(getConfigurationClassLoader()); - String authType; - String authAlias; - if(strResult.contains("@@zaken-api.jwt@@")){ - authType = appConstants.getProperty("zaakbrug.zgw.zaken-api.auth-type", ""); // "jwt", "basic", "value" - authAlias = appConstants.getProperty("zaakbrug.zgw.zaken-api.auth-alias", ""); - } else if(strResult.contains("@@documenten-api.jwt@@")){ - authType = appConstants.getProperty("zaakbrug.zgw.documenten-api.auth-type", ""); // "jwt", "basic", "value" - authAlias = appConstants.getProperty("zaakbrug.zgw.documenten-api.auth-alias", ""); - } else if(strResult.contains("@@catalogi-api.jwt@@")){ - authType = appConstants.getProperty("zaakbrug.zgw.catalogi-api.auth-type", ""); // "jwt", "basic", "value" - authAlias = appConstants.getProperty("zaakbrug.zgw.catalogi-api.auth-alias", ""); - } else if(strResult.contains("@@besluiten-api.jwt@@")){ - authType = appConstants.getProperty("zaakbrug.zgw.besluiten-api.auth-type", ""); // "jwt", "basic", "value" - authAlias = appConstants.getProperty("zaakbrug.zgw.besluiten-api.auth-alias", ""); - } else { - throw new ParameterException("Parameter ["+getName()+"] unable to resolve ["+strResult+"] to a known api type"); - } - - CredentialFactory credentialFactory = new CredentialFactory(authAlias); - String username = credentialFactory.getUsername(); - String secret = credentialFactory.getPassword(); - if("jwt".equalsIgnoreCase(authType)){ - // Copied from https://github.com/Sudwest-Fryslan/OpenZaakBrug/blob/master/src/main/java/nl/haarlem/translations/zdstozgw/translation/zgw/client/JWTService.java - Signer signer = HMACSigner.newSHA256Signer(secret); - io.fusionauth.jwt.domain.JWT jwt = new io.fusionauth.jwt.domain.JWT().setIssuer(username) - .setIssuedAt(now(ZoneOffset.UTC)).addClaim("client_id", username).addClaim("user_id", username) - .addClaim("user_reresentation", username).setExpiration(now(ZoneOffset.UTC).plusMinutes(10)); - String jwtToken = io.fusionauth.jwt.domain.JWT.getEncoder().encode(jwt, signer); - result = "Bearer " + jwtToken; - } else if ("basic".equalsIgnoreCase(authType)){ - String encoded = Base64.getEncoder().encodeToString((username + ":" + secret).getBytes()); - result = "Basic " + encoded; - } else if ("value".equalsIgnoreCase(authType)){ - result = secret; - } else { - throw new ParameterException("Parameter ["+getName()+"] unknown auth-type ["+authType+"], must be 'jwt', 'basic' or 'value'"); - } - } - } else { - try { - if (message==null) { - return null; - } - if (StringUtils.isNotEmpty(getContextKey())) { - result = message.getContext().get(getContextKey()); - } else { - message.preserve(); - result=message; - } - } catch (IOException e) { - throw new ParameterException(getName(), e); - } - } - } - - if (result instanceof Message) { //we just need to check if the message is null or not! - Message resultMessage = (Message) result; - if (Message.isNull(resultMessage)) { - result = null; - } else if (resultMessage.isRequestOfType(String.class)) { //Used by getMinLength and getMaxLength - try { - result = resultMessage.asString(); - } catch (IOException ignored) { - // Already checked for String, so this should never happen - } - } - } - if (result != null && !"".equals(result)) { - final Object finalResult = result; - LOG.debug("Parameter [{}] resolved to [{}]", this::getName, ()-> isHidden() ? hide(finalResult.toString()) : finalResult); - } else { - // if result is empty then return specified default value - Object valueByDefault=null; - Iterator it = getDefaultValueMethodsList().iterator(); - while (valueByDefault == null && it.hasNext()) { - DefaultValueMethods method = it.next(); - switch(method) { - case DEFAULTVALUE: - valueByDefault = getDefaultValue(); - break; - case SESSIONKEY: - valueByDefault = session.get(requestedSessionKey); - break; - case PATTERN: - valueByDefault = formatPattern(alreadyResolvedParameters, session); - break; - case VALUE: - valueByDefault = getValue(); - break; - case INPUT: - try { - message.preserve(); - valueByDefault=message.asString(); - } catch (IOException e) { - throw new ParameterException(getName(), e); - } - break; - default: - throw new IllegalArgumentException("Unknown defaultValues method ["+method+"]"); - } - } - if (valueByDefault!=null) { - result = valueByDefault; - final Object finalResult = result; - LOG.debug("Parameter [{}] resolved to default value [{}]", this::getName, ()-> isHidden() ? hide(finalResult.toString()) : finalResult); - } - } - if (result instanceof String) { - if (getMinLength()>=0 && getType()!=ParameterType.NUMBER) { - final String stringResult = (String) result; - if (stringResult.length() < getMinLength()) { - LOG.debug("Padding parameter [{}] because length [{}] falls short of minLength [{}]", this::getName, stringResult::length, this::getMinLength); - result = StringUtils.rightPad(stringResult, getMinLength()); - } - } - if (getMaxLength()>=0) { - final String stringResult = (String) result; - if (stringResult.length() > getMaxLength()) { - LOG.debug("Trimming parameter [{}] because length [{}] exceeds maxLength [{}]", this::getName, stringResult::length, this::getMaxLength); - result = stringResult.substring(0, getMaxLength()); - } - } - } - if(result !=null && getType().requiresTypeConversion) { - result = getValueAsType(result, namespaceAware); - } - if (result instanceof Number) { - if (getMinInclusiveString()!=null && ((Number)result).floatValue() < minInclusive.floatValue()) { - LOG.debug("Replacing parameter [{}] because value [{}] falls short of minInclusive [{}]", this::getName, logValue(result), this::getMinInclusiveString); - result = minInclusive; - } - if (getMaxInclusiveString()!=null && ((Number)result).floatValue() > maxInclusive.floatValue()) { - LOG.debug("Replacing parameter [{}] because value [{}] exceeds maxInclusive [{}]", this::getName, logValue(result), this::getMaxInclusiveString); - result = maxInclusive; - } - } - if (getType()==ParameterType.NUMBER && getMinLength()>=0 && (result+"").length()finalResult.getClass().getName(), ()-> finalResult); - } catch (DomBuilderException | IOException | XmlException e) { - throw new ParameterException(getName(), "Parameter ["+getName()+"] could not parse result ["+requestMessage+"] to XML nodeset",e); - } - break; - case DOMDOC: - try { - if (isRemoveNamespaces()) { - requestMessage = XmlUtils.removeNamespaces(requestMessage); - } - if(request instanceof Document) { - return request; - } - result = XmlUtils.buildDomDocument(requestMessage.asInputSource(), namespaceAware); - final Object finalResult = result; - LOG.debug("final result [{}][{}]", ()->finalResult.getClass().getName(), ()-> finalResult); - } catch (DomBuilderException | IOException | XmlException e) { - throw new ParameterException(getName(), "Parameter ["+getName()+"] could not parse result ["+requestMessage+"] to XML document",e); - } - break; - case DATE: - case DATETIME: - case TIMESTAMP: - case TIME: { - if (request instanceof Date) { - return request; - } - Message finalRequestMessage = requestMessage; - LOG.debug("Parameter [{}] converting result [{}] to Date using formatString [{}]", this::getName, () -> finalRequestMessage, this::getFormatString); - DateFormat df = new SimpleDateFormat(getFormatString()); - try { - result = df.parseObject(requestMessage.asString()); - } catch (ParseException e) { - throw new ParameterException(getName(), "Parameter [" + getName() + "] could not parse result [" + requestMessage + "] to Date using formatString [" + getFormatString() + "]", e); - } - break; - } - case XMLDATETIME: { - if (request instanceof Date) { - return request; - } - Message finalRequestMessage = requestMessage; - LOG.debug("Parameter [{}] converting result [{}] from XML dateTime to Date", this::getName, () -> finalRequestMessage); - result = XmlUtils.parseXmlDateTime(requestMessage.asString()); - break; - } - case NUMBER: { - if (request instanceof Number) { - return request; - } - Message finalRequestMessage = requestMessage; - LOG.debug("Parameter [{}] converting result [{}] to number decimalSeparator [{}] groupingSeparator [{}]", this::getName, ()->finalRequestMessage, decimalFormatSymbols::getDecimalSeparator, decimalFormatSymbols::getGroupingSeparator); - DecimalFormat decimalFormat = new DecimalFormat(); - decimalFormat.setDecimalFormatSymbols(decimalFormatSymbols); - try { - result = decimalFormat.parse(requestMessage.asString()); - } catch (ParseException e) { - throw new ParameterException(getName(), "Parameter [" + getName() + "] could not parse result [" + requestMessage + "] to number decimalSeparator [" + decimalFormatSymbols.getDecimalSeparator() + "] groupingSeparator [" + decimalFormatSymbols.getGroupingSeparator() + "]", e); - } - break; - } - case INTEGER: { - if (request instanceof Integer) { - return request; - } - Message finalRequestMessage = requestMessage; - LOG.debug("Parameter [{}] converting result [{}] to integer", this::getName, ()->finalRequestMessage); - try { - result = Integer.parseInt(requestMessage.asString()); - } catch (NumberFormatException e) { - throw new ParameterException(getName(), "Parameter [" + getName() + "] could not parse result [" + requestMessage + "] to integer", e); - } - break; - } - case BOOLEAN: { - if (request instanceof Boolean) { - return request; - } - Message finalRequestMessage = requestMessage; - LOG.debug("Parameter [{}] converting result [{}] to boolean", this::getName, ()->finalRequestMessage); - result = Boolean.parseBoolean(requestMessage.asString()); - break; - } - default: - break; - } - } catch(IOException e) { - throw new ParameterException(getName(), "Could not convert parameter ["+getName()+"] to String", e); - } - - return result; - } - - private String formatPattern(ParameterValueList alreadyResolvedParameters, PipeLineSession session) throws ParameterException { - int startNdx; - int endNdx = 0; - - // replace the named parameter with numbered parameters - StringBuilder formatPattern = new StringBuilder(); - List params = new ArrayList<>(); - int paramPosition = 0; - while(true) { - // get name of parameter in pattern to be substituted - startNdx = pattern.indexOf("{", endNdx); - if (startNdx == -1) { - formatPattern.append(pattern.substring(endNdx)); - break; - } - else { - formatPattern.append(pattern, endNdx, startNdx); - } - int tmpEndNdx = pattern.indexOf("}", startNdx); - endNdx = pattern.indexOf(",", startNdx); - if (endNdx == -1 || endNdx > tmpEndNdx) { - endNdx = tmpEndNdx; - } - if (endNdx == -1) { - throw new ParameterException(getName(), new ParseException("Bracket is not closed", startNdx)); - } - String substitutionPattern = pattern.substring(startNdx + 1, tmpEndNdx); - - // get value - Object substitutionValue = getValueForFormatting(alreadyResolvedParameters, session, substitutionPattern); - params.add(substitutionValue); - formatPattern.append('{').append(paramPosition++); - } - try { - return MessageFormat.format(formatPattern.toString(), params.toArray()); - } catch (Exception e) { - throw new ParameterException(getName(), "Cannot parse ["+formatPattern.toString()+"]", e); - } - } - - private Object preFormatDateType(Object rawValue, String formatType, String patternFormatString) throws ParameterException { - if (formatType!=null && (formatType.equalsIgnoreCase("date") || formatType.equalsIgnoreCase("time"))) { - if (rawValue instanceof Date) { - return rawValue; - } - DateFormat df = new SimpleDateFormat(StringUtils.isNotEmpty(patternFormatString) ? patternFormatString : DateFormatUtils.FORMAT_DATETIME_GENERIC); - try { - return df.parse(Message.asString(rawValue)); - } catch (ParseException | IOException e) { - throw new ParameterException(getName(), "Cannot parse ["+rawValue+"] as date", e); - } - } - if (rawValue instanceof Date) { - DateFormat df = new SimpleDateFormat(StringUtils.isNotEmpty(patternFormatString) ? patternFormatString : DateFormatUtils.FORMAT_DATETIME_GENERIC); - return df.format(rawValue); - } - try { - return Message.asString(rawValue); - } catch (IOException e) { - throw new ParameterException(getName(), "Cannot read date value ["+rawValue+"]", e); - } - } - - - private Object getValueForFormatting(ParameterValueList alreadyResolvedParameters, PipeLineSession session, String targetPattern) throws ParameterException { - String[] patternElements = targetPattern.split(","); - String name = patternElements[0].trim(); - String formatType = patternElements.length>1 ? patternElements[1].trim() : null; - String formatString = patternElements.length>2 ? patternElements[2].trim() : null; - - ParameterValue paramValue = alreadyResolvedParameters.get(name); - Object substitutionValue = paramValue == null ? null : paramValue.getValue(); - - if (substitutionValue == null) { - Object substitutionValueMessage = session.get(name); - if (substitutionValueMessage != null) { - if (substitutionValueMessage instanceof Date) { - substitutionValue = preFormatDateType(substitutionValueMessage, formatType, formatString); - } else { - if (substitutionValueMessage instanceof String) { - substitutionValue = substitutionValueMessage; - } else { - try { - Message message = Message.asMessage(substitutionValueMessage); // Do not close object from session here; might be reused later - substitutionValue = message.asString(); - } catch (IOException e) { - throw new ParameterException(getName(), "Cannot get substitution value from session key: " + name, e); - } - } - if (substitutionValue == null) throw new ParameterException(getName(), "Cannot get substitution value from session key: " + name); - } - } - } - if (substitutionValue == null) { - String namelc=name.toLowerCase(); - switch (namelc) { - case "now": - substitutionValue = preFormatDateType(new Date(), formatType, formatString); - break; - case "uid": - substitutionValue = UUIDUtil.createSimpleUUID(); - break; - case "uuid": - substitutionValue = UUIDUtil.createRandomUUID(); - break; - case "hostname": - substitutionValue = Misc.getHostname(); - break; - case "fixeddate": - if (!ConfigurationUtils.isConfigurationStubbed(configurationClassLoader)) { - throw new ParameterException(getName(), "Parameter pattern [" + name + "] only allowed in stub mode"); - } - Object fixedDateTime = session.get(PutSystemDateInSession.FIXEDDATE_STUB4TESTTOOL_KEY); - if (fixedDateTime == null) { - DateFormat df = new SimpleDateFormat(DateFormatUtils.FORMAT_DATETIME_GENERIC); - try { - fixedDateTime = df.parse(PutSystemDateInSession.FIXEDDATETIME); - } catch (ParseException e) { - throw new ParameterException(getName(), "Could not parse FIXEDDATETIME [" + PutSystemDateInSession.FIXEDDATETIME + "]", e); - } - } - substitutionValue = preFormatDateType(fixedDateTime, formatType, formatString); - break; - case "fixeduid": - if (!ConfigurationUtils.isConfigurationStubbed(configurationClassLoader)) { - throw new ParameterException(getName(), "Parameter pattern [" + name + "] only allowed in stub mode"); - } - substitutionValue = FIXEDUID; - break; - case "fixedhostname": - if (!ConfigurationUtils.isConfigurationStubbed(configurationClassLoader)) { - throw new ParameterException(getName(), "Parameter pattern [" + name + "] only allowed in stub mode"); - } - substitutionValue = FIXEDHOSTNAME; - break; - case "username": - substitutionValue = cf != null ? cf.getUsername() : ""; - break; - case "password": - substitutionValue = cf != null ? cf.getPassword() : ""; - break; - } - } - if (substitutionValue == null) { - if (isIgnoreUnresolvablePatternElements()) { - substitutionValue=""; - } else { - throw new ParameterException(getName(), "Parameter or session variable with name [" + name + "] in pattern [" + getPattern() + "] cannot be resolved"); - } - } - return substitutionValue; - } - - @Override - public String toString() { - return "Parameter name=[" + name + "] defaultValue=[" + defaultValue + "] sessionKey=[" + sessionKey + "] sessionKeyXPath=[" + sessionKeyXPath + "] xpathExpression=[" + xpathExpression + "] type=[" + type + "] value=[" + value + "]"; - } - - private TransformerPool getTransformerPool() { - return transformerPool; - } - - /** Name of the parameter */ - @Override - public void setName(String parameterName) { - name = parameterName; - } - @Override - public String getName() { - return name; - } - - /** The target data type of the parameter, related to the database or XSLT stylesheet to which the parameter is applied. */ - public void setType(ParameterType type) { - this.type = type; - } - - /** The value of the parameter, or the base for transformation using xpathExpression or stylesheet, or formatting. */ - public void setValue(String value) { - this.value = value; - } - - /** - * Key of a PipelineSession-variable.
If specified, the value of the PipelineSession variable is used as input for - * the xpathExpression or stylesheet, instead of the current input message.
If no xpathExpression or stylesheet are - * specified, the value itself is returned.
If the value '*' is specified, all existing sessionkeys are added as - * parameter of which the name starts with the name of this parameter.
If also the name of the parameter has the - * value '*' then all existing sessionkeys are added as parameter (except tsReceived) - */ - public void setSessionKey(String string) { - sessionKey = string; - } - - /** key of message context variable to use as source, instead of the message found from input message or sessionKey itself */ - public void setContextKey(String string) { - contextKey = string; - } - - /** Instead of a fixed sessionKey it's also possible to use a XPath expression applied to the input message to extract the name of the session-variable. */ - public void setSessionKeyXPath(String string) { - sessionKeyXPath = string; - } - - /** URL to a stylesheet that wil be applied to the contents of the message or the value of the session-variable. */ - public void setStyleSheetName(String stylesheetName){ - this.styleSheetName=stylesheetName; - } - - /** the XPath expression to extract the parameter value from the (xml formatted) input or session-variable. */ - public void setXpathExpression(String xpathExpression) { - this.xpathExpression = xpathExpression; - } - - /** - * If set to 2 or 3 a Saxon (net.sf.saxon) xslt processor 2.0 or 3.0 respectively will be used, otherwise xslt processor 1.0 (org.apache.xalan). 0 will auto-detect - * @ff.default 0 - */ - public void setXsltVersion(int xsltVersion) { - this.xsltVersion=xsltVersion; - } - - /** - * Namespace definitions for xpathExpression. Must be in the form of a comma or space separated list of - * prefix=namespaceuri-definitions. One entry can be without a prefix, that will define the default namespace. - */ - public void setNamespaceDefs(String namespaceDefs) { - this.namespaceDefs = namespaceDefs; - } - - /** - * When set true namespaces (and prefixes) in the input message are removed before the stylesheet/xpathExpression is executed - * @ff.default false - */ - public void setRemoveNamespaces(boolean b) { - removeNamespaces = b; - } - - /** If the result of sessionKey, xpathExpression and/or stylesheet returns null or an empty string, this value is returned */ - public void setDefaultValue(String string) { - defaultValue = string; - } - - /** - * Comma separated list of methods (defaultValue, sessionKey, pattern, value or input) to use as default value. Used in the order they appear until a non-null value is found. - * @ff.default defaultValue - */ - public void setDefaultValueMethods(String string) { - defaultValueMethods = string; - } - - /** - * Value of parameter is determined using substitution and formatting, following MessageFormat syntax with named parameters. The expression can contain references - * to session-variables or other parameters using the {name-of-parameter} and is formatted using java.text.MessageFormat. - *
NB: When referencing other parameters these MUST be defined before the parameter using pattern substitution. - *
- *
- * If for instance fname is a parameter or session-variable that resolves to Eric, then the pattern - * 'Hi {fname}, how do you do?' resolves to 'Hi Eric, do you do?'.
- * The following predefined reference can be used in the expression too:
    - *
  • {now}: the current system time
  • - *
  • {uid}: an unique identifier, based on the IP address and java.rmi.server.UID
  • - *
  • {uuid}: an unique identifier, based on the IP address and java.util.UUID
  • - *
  • {hostname}: the name of the machine the application runs on
  • - *
  • {username}: username from the credentials found using authAlias, or the username attribute
  • - *
  • {password}: password from the credentials found using authAlias, or the password attribute
  • - *
  • {fixeddate}: fake date, for testing only
  • - *
  • {fixeduid}: fake uid, for testing only
  • - *
  • {fixedhostname}: fake hostname, for testing only
  • - *
- * A guid can be generated using {hostname}_{uid}, see also - * http://java.sun.com/j2se/1.4.2/docs/api/java/rmi/server/uid.html for more information about (g)uid's or - * http://docs.oracle.com/javase/1.5.0/docs/api/java/util/uuid.html for more information about uuid's. - *
- * When combining a date or time pattern like {now} or {fixeddate} with a DATE, TIME, DATETIME or TIMESTAMP type, the effective value of the attribute - * formatString must match the effective value of the formatString in the pattern. - */ - public void setPattern(String string) { - pattern = string; - } - - /** Alias used to obtain username and password, used when a pattern containing {username} or {password} is specified */ - public void setAuthAlias(String string) { - authAlias = string; - } - - /** Default username that is used when a pattern containing {username} is specified */ - public void setUsername(String string) { - username = string; - } - - /** Default password that is used when a pattern containing {password} is specified */ - public void setPassword(String string) { - password = string; - } - - /** If set true pattern elements that cannot be resolved to a parameter or sessionKey are silently resolved to an empty string */ - public void setIgnoreUnresolvablePatternElements(boolean b) { - ignoreUnresolvablePatternElements = b; - } - - /** - * Used in combination with types DATE, TIME, DATETIME and TIMESTAMP to parse the raw parameter string data into an object of the respective type - * @ff.default depends on type - */ - public void setFormatString(String string) { - formatString = string; - } - - /** - * Used in combination with type NUMBER - * @ff.default system default - */ - public void setDecimalSeparator(String string) { - decimalSeparator = string; - } - - /** - * Used in combination with type NUMBER - * @ff.default system default - */ - public void setGroupingSeparator(String string) { - groupingSeparator = string; - } - - /** - * If set (>=0) and the length of the value of the parameter falls short of this minimum length, the value is padded - * @ff.default -1 - */ - public void setMinLength(int i) { - minLength = i; - } - - /** - * If set (>=0) and the length of the value of the parameter exceeds this maximum length, the length is trimmed to this maximum length - * @ff.default -1 - */ - public void setMaxLength(int i) { - maxLength = i; - } - - /** Used in combination with type number; if set and the value of the parameter exceeds this maximum value, this maximum value is taken */ - public void setMaxInclusive(String string) { - maxInclusiveString = string; - } - - /** Used in combination with type number; if set and the value of the parameter falls short of this minimum value, this minimum value is taken */ - public void setMinInclusive(String string) { - minInclusiveString = string; - } - - /** - * If set to true, the value of the parameter will not be shown in the log (replaced by asterisks) - * @ff.default false - */ - public void setHidden(boolean b) { - hidden = b; - } - - /** - * Set the mode of the parameter, which determines if the parameter is an INPUT, OUTPUT, or INOUT. - * This parameter only has effect for {@link StoredProcedureQuerySender}. - * An OUTPUT parameter does not need to have a value specified, but does need to have the type specified. - * Parameter values will not be updated, but output values will be put into the result of the - * {@link StoredProcedureQuerySender}. - * - * If not specified, the default is INPUT. - * - * @param mode INPUT, OUTPUT or INOUT. - */ - public void setMode(ParameterMode mode) { - this.mode = mode; - } -} \ No newline at end of file diff --git a/src/main/java/org/frankframework/parameters/Parameter.java-orig b/src/main/java/org/frankframework/parameters/Parameter.java-orig deleted file mode 100644 index 7d3ec2add..000000000 --- a/src/main/java/org/frankframework/parameters/Parameter.java-orig +++ /dev/null @@ -1,1137 +0,0 @@ -/* - Copyright 2013, 2016, 2019, 2020 Nationale-Nederlanden, 2021-2023 WeAreFrank! - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -package org.frankframework.parameters; - -import static org.frankframework.functional.FunctionalUtil.logValue; -import static org.frankframework.util.StringUtil.hide; - -import java.io.IOException; -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.MessageFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import javax.xml.transform.Source; -import javax.xml.transform.TransformerException; -import javax.xml.transform.dom.DOMResult; - -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.frankframework.configuration.ConfigurationException; -import org.frankframework.configuration.ConfigurationUtils; -import org.frankframework.configuration.ConfigurationWarning; -import org.frankframework.core.IConfigurable; -import org.frankframework.core.IWithParameters; -import org.frankframework.core.ParameterException; -import org.frankframework.core.PipeLineSession; -import org.frankframework.doc.DocumentedEnum; -import org.frankframework.doc.EnumLabel; -import org.frankframework.jdbc.StoredProcedureQuerySender; -import org.frankframework.pipes.PutSystemDateInSession; -import org.frankframework.stream.Message; -import org.frankframework.util.CredentialFactory; -import org.frankframework.util.DateFormatUtils; -import org.frankframework.util.DomBuilderException; -import org.frankframework.util.EnumUtils; -import org.frankframework.util.Misc; -import org.frankframework.util.StringUtil; -import org.frankframework.util.TransformerPool; -import org.frankframework.util.TransformerPool.OutputType; -import org.frankframework.util.UUIDUtil; -import org.frankframework.util.XmlBuilder; -import org.frankframework.util.XmlException; -import org.frankframework.util.XmlUtils; -import org.springframework.context.ApplicationContext; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import lombok.Getter; -import lombok.Setter; - -/** - * Generic parameter definition. - * - * A parameter resembles an attribute. However, while attributes get their value at configuration-time, - * parameters get their value at the time of processing the message. Value can be retrieved from the message itself, - * a fixed value, or from the pipelineSession. If this does not result in a value (or if neither of these is specified), a default value - * can be specified. If an XPathExpression or stylesheet is specified, it will be applied to the message, the value retrieved - * from the pipelineSession or the fixed value specified. If the transformation produces no output, the default value - * of the parameter is taken if provided. - *

- * Examples: - *

- * stored under SessionKey 'TransportInfo':
- *  <transportinfo>
- *   <to>***@zonnet.nl</to>
- *   <to>***@zonnet.nl</to>
- *   <cc>***@zonnet.nl</cc>
- *  </transportinfo>
- *
- * to obtain all 'to' addressees as a parameter:
- * sessionKey="TransportInfo"
- * xpathExpression="transportinfo/to"
- * type="xml"
- *
- * Result:
- *   <to>***@zonnet.nl</to>
- *   <to>***@zonnet.nl</to>
- * 
- * - * N.B. to obtain a fixed value: a non-existing 'dummy' sessionKey in combination with the fixed value in defaultValue is used traditionally. - * The current version of parameter supports the 'value' attribute, that is sufficient to set a fixed value. - * @author Gerrit van Brakel - * @ff.parameters Parameters themselves can have parameters too, for instance if a XSLT transformation is used, that transformation can have parameters. - */ -public class Parameter implements IConfigurable, IWithParameters { - private static final Logger LOG = LogManager.getLogger(Parameter.class); - private final @Getter ClassLoader configurationClassLoader = Thread.currentThread().getContextClassLoader(); - private @Getter @Setter ApplicationContext applicationContext; - - public static final String TYPE_DATE_PATTERN="yyyy-MM-dd"; - public static final String TYPE_TIME_PATTERN="HH:mm:ss"; - public static final String TYPE_DATETIME_PATTERN="yyyy-MM-dd HH:mm:ss"; - public static final String TYPE_TIMESTAMP_PATTERN= DateFormatUtils.FORMAT_FULL_GENERIC; - - public static final String FIXEDUID ="0a1b234c--56de7fa8_9012345678b_-9cd0"; - public static final String FIXEDHOSTNAME ="MYHOST000012345"; - - private String name = null; - private @Getter ParameterType type = ParameterType.STRING; - private @Getter String sessionKey = null; - private @Getter String sessionKeyXPath = null; - private @Getter String contextKey = null; - private @Getter String xpathExpression = null; - private @Getter String namespaceDefs = null; - private @Getter String styleSheetName = null; - private @Getter String pattern = null; - private @Getter String authAlias; - private @Getter String username; - private @Getter String password; - private @Getter boolean ignoreUnresolvablePatternElements = false; - private @Getter String defaultValue = null; - private @Getter String defaultValueMethods = "defaultValue"; - private @Getter String value = null; - private @Getter String formatString = null; - private @Getter String decimalSeparator = null; - private @Getter String groupingSeparator = null; - private @Getter int minLength = -1; - private @Getter int maxLength = -1; - private @Getter String minInclusiveString = null; - private @Getter String maxInclusiveString = null; - private Number minInclusive; - private Number maxInclusive; - private @Getter boolean hidden = false; - private @Getter boolean removeNamespaces=false; - private @Getter int xsltVersion = 0; // set to 0 for auto-detect. - - private @Getter DecimalFormatSymbols decimalFormatSymbols = null; - private TransformerPool transformerPool = null; - private TransformerPool tpDynamicSessionKey = null; - protected ParameterList paramList = null; - private boolean configured = false; - private CredentialFactory cf; - - private List defaultValueMethodsList; - - @Getter - private ParameterMode mode = ParameterMode.INPUT; - - public enum ParameterMode { - INPUT, OUTPUT, INOUT - } - - public enum ParameterType { - /** Renders the contents of the first node (in combination with xslt or xpath). Please note that - * if there are child nodes, only the contents are returned, use XML if the xml tags are required */ - STRING, - - /** Renders an xml-nodeset as an xml-string (in combination with xslt or xpath). This will include the xml tags */ - XML, - - /** Renders the CONTENTS of the first node as a nodeset - * that can be used as such when passed as xslt-parameter (only for XSLT 1.0). - * Please note that the nodeset may contain multiple nodes, without a common root node. - * N.B. The result is the set of children of what you might expect it to be... */ - NODE(true), - - /** Renders XML as a DOM document; similar to node - with the distinction that there is always a common root node (required for XSLT 2.0) */ - DOMDOC(true), - - /** Converts the result to a Date, by default using formatString yyyy-MM-dd. - * When applied as a JDBC parameter, the method setDate() is used */ - DATE(true), - - /** Converts the result to a Date, by default using formatString HH:mm:ss. - * When applied as a JDBC parameter, the method setTime() is used */ - TIME(true), - - /** Converts the result to a Date, by default using formatString yyyy-MM-dd HH:mm:ss. - * When applied as a JDBC parameter, the method setTimestamp() is used */ - DATETIME(true), - - /** Similar to DATETIME, except for the formatString that is yyyy-MM-dd HH:mm:ss.SSS by default */ - TIMESTAMP(true), - - /** Converts the result from a XML formatted dateTime to a Date. - * When applied as a JDBC parameter, the method setTimestamp() is used */ - XMLDATETIME(true), - - /** Converts the result to a Number, using decimalSeparator and groupingSeparator. - * When applied as a JDBC parameter, the method setDouble() is used */ - NUMBER(true), - - /** Converts the result to an Integer */ - INTEGER(true), - - /** Converts the result to a Boolean */ - BOOLEAN(true), - - /** Only applicable as a JDBC parameter, the method setBinaryStream() is used */ - @ConfigurationWarning("use type [BINARY] instead") - @Deprecated INPUTSTREAM, - - /** Only applicable as a JDBC parameter, the method setBytes() is used */ - @ConfigurationWarning("use type [BINARY] instead") - @Deprecated BYTES, - - /** Forces the parameter value to be treated as binary data (e.g. when using a SQL BLOB field). - * When applied as a JDBC parameter, the method setBinaryStream() or setBytes() is used */ - BINARY, - - /** Forces the parameter value to be treated as character data (e.g. when using a SQL CLOB field). - * When applied as a JDBC parameter, the method setCharacterStream() or setString() is used */ - CHARACTER, - - /** - * Used for StoredProcedure OUT parameters when the database type is a {@code CURSOR} or {@link java.sql.JDBCType#REF_CURSOR}. - * See also {@link org.frankframework.jdbc.StoredProcedureQuerySender}. - *
- * DEPRECATED: Type LIST can also be used in larva test to Convert a List to an xml-string (<items><item>...</item><item>...</item></items>) */ - LIST, - - /** (Used in larva only) Converts a Map<String, String> object to a xml-string (<items><item name='...'>...</item><item name='...'>...</item></items>) */ - @Deprecated MAP; - - public final boolean requiresTypeConversion; - - private ParameterType() { - this(false); - } - - private ParameterType(boolean requiresTypeConverion) { - this.requiresTypeConversion = requiresTypeConverion; - } - - } - - public enum DefaultValueMethods implements DocumentedEnum { - @EnumLabel("defaultValue") DEFAULTVALUE, - @EnumLabel("sessionKey") SESSIONKEY, - @EnumLabel("pattern") PATTERN, - @EnumLabel("value") VALUE, - @EnumLabel("input") INPUT; - } - - public Parameter() { - super(); - } - - /** utility constructor, useful for unit testing */ - public Parameter(String name, String value) { - this(); - this.name = name; - this.value = value; - } - - @Override - public void addParameter(Parameter p) { - if (paramList==null) { - paramList=new ParameterList(); - } - paramList.add(p); - } - - @Override - public ParameterList getParameterList() { - return paramList; - } - - @Override - public void configure() throws ConfigurationException { - if (StringUtils.isNotEmpty(getSessionKey()) && StringUtils.isNotEmpty(getSessionKeyXPath())) { - throw new ConfigurationException("Parameter ["+getName()+"] cannot have both sessionKey and sessionKeyXPath specified"); - } - if (StringUtils.isNotEmpty(getXpathExpression()) || StringUtils.isNotEmpty(styleSheetName)) { - if (paramList!=null) { - paramList.configure(); - } - OutputType outputType = getType() == ParameterType.XML || getType() == ParameterType.NODE || getType() == ParameterType.DOMDOC ? OutputType.XML : OutputType.TEXT; - boolean includeXmlDeclaration = false; - - transformerPool = TransformerPool.configureTransformer0(this, getNamespaceDefs(), getXpathExpression(), getStyleSheetName(), outputType, includeXmlDeclaration, paramList, getXsltVersion()); - } else { - if (paramList != null && StringUtils.isEmpty(getPattern())) { - throw new ConfigurationException("Parameter [" + getName() + "] can only have parameters itself if a styleSheetName, xpathExpression or pattern is specified"); - } - } - if (StringUtils.isNotEmpty(getSessionKeyXPath())) { - tpDynamicSessionKey = TransformerPool.configureTransformer(this, getNamespaceDefs(), getSessionKeyXPath(), null, OutputType.TEXT,false,null); - } - if (getType() == null) { - LOG.info("parameter [{} has no type. Setting the type to [{}]", this::getType, ()->ParameterType.STRING); - setType(ParameterType.STRING); - } - if(StringUtils.isEmpty(getFormatString())) { - switch(getType()) { - case DATE: - setFormatString(TYPE_DATE_PATTERN); - break; - case DATETIME: - setFormatString(TYPE_DATETIME_PATTERN); - break; - case TIMESTAMP: - setFormatString(TYPE_TIMESTAMP_PATTERN); - break; - case TIME: - setFormatString(TYPE_TIME_PATTERN); - break; - default: - break; - } - } - if (getType()==ParameterType.NUMBER) { - decimalFormatSymbols = new DecimalFormatSymbols(); - if (StringUtils.isNotEmpty(getDecimalSeparator())) { - decimalFormatSymbols.setDecimalSeparator(getDecimalSeparator().charAt(0)); - } - if (StringUtils.isNotEmpty(getGroupingSeparator())) { - decimalFormatSymbols.setGroupingSeparator(getGroupingSeparator().charAt(0)); - } - } - configured = true; - - if (getMinInclusiveString()!=null || getMaxInclusiveString()!=null) { - if (getType()!=ParameterType.NUMBER) { - throw new ConfigurationException("minInclusive and maxInclusive only allowed in combination with type ["+ParameterType.NUMBER+"]"); - } - if (getMinInclusiveString()!=null) { - DecimalFormat df = new DecimalFormat(); - df.setDecimalFormatSymbols(decimalFormatSymbols); - try { - minInclusive = df.parse(getMinInclusiveString()); - } catch (ParseException e) { - throw new ConfigurationException("Attribute [minInclusive] could not parse result ["+getMinInclusiveString()+"] to number; decimalSeparator ["+decimalFormatSymbols.getDecimalSeparator()+"] groupingSeparator ["+decimalFormatSymbols.getGroupingSeparator()+"]",e); - } - } - if (getMaxInclusiveString()!=null) { - DecimalFormat df = new DecimalFormat(); - df.setDecimalFormatSymbols(decimalFormatSymbols); - try { - maxInclusive = df.parse(getMaxInclusiveString()); - } catch (ParseException e) { - throw new ConfigurationException("Attribute [maxInclusive] could not parse result ["+getMaxInclusiveString()+"] to number; decimalSeparator ["+decimalFormatSymbols.getDecimalSeparator()+"] groupingSeparator ["+decimalFormatSymbols.getGroupingSeparator()+"]",e); - } - } - } - if (StringUtils.isNotEmpty(getAuthAlias()) || StringUtils.isNotEmpty(getUsername()) || StringUtils.isNotEmpty(getPassword())) { - cf=new CredentialFactory(getAuthAlias(), getUsername(), getPassword()); - } - } - - private List getDefaultValueMethodsList() { - if (defaultValueMethodsList == null) { - defaultValueMethodsList = StringUtil.splitToStream(getDefaultValueMethods(), ", ") - .map(token -> EnumUtils.parse(DefaultValueMethods.class, token)) - .collect(Collectors.toList()); - } - return defaultValueMethodsList; - } - - private Document transformToDocument(Source xmlSource, ParameterValueList pvl) throws TransformerException, IOException { - TransformerPool pool = getTransformerPool(); - DOMResult transformResult = new DOMResult(); - pool.transform(xmlSource,transformResult, pvl); - return (Document) transformResult.getNode(); - } - - public boolean isWildcardSessionKey() { - return "*".equals(getSessionKey()); - } - /** - * if this returns true, then the input value must be repeatable, as it might be used multiple times. - */ - public boolean requiresInputValueForResolution() { - if (tpDynamicSessionKey != null) { // tpDynamicSessionKey is applied to the input message to retrieve the session key - return true; - } - return StringUtils.isEmpty(getContextKey()) && - (StringUtils.isEmpty(getSessionKey()) && StringUtils.isEmpty(getValue()) && StringUtils.isEmpty(getPattern()) - || getDefaultValueMethodsList().contains(DefaultValueMethods.INPUT) - ); - } - - public boolean requiresInputValueOrContextForResolution() { - if (tpDynamicSessionKey != null) { // tpDynamicSessionKey is applied to the input message to retrieve the session key - return true; - } - return StringUtils.isEmpty(getSessionKey()) && StringUtils.isEmpty(getValue()) && StringUtils.isEmpty(getPattern()) - || getDefaultValueMethodsList().contains(DefaultValueMethods.INPUT); - } - - public boolean consumesSessionVariable(String sessionKey) { - return StringUtils.isEmpty(getContextKey()) && ( - sessionKey.equals(getSessionKey()) - || getPattern()!=null && getPattern().contains("{"+sessionKey+"}") - || getParameterList()!=null && getParameterList().consumesSessionVariable(sessionKey) - ); - } - - /** - * determines the raw value - */ - public Object getValue(ParameterValueList alreadyResolvedParameters, Message message, PipeLineSession session, boolean namespaceAware) throws ParameterException { - Object result = null; - LOG.debug("Calculating value for Parameter [{}]", this::getName); - if (!configured) { - throw new ParameterException(getName(), "Parameter ["+getName()+"] not configured"); - } - - String requestedSessionKey; - if (tpDynamicSessionKey != null) { - try { - requestedSessionKey = tpDynamicSessionKey.transform(message.asSource()); - } catch (Exception e) { - throw new ParameterException(getName(), "SessionKey for parameter ["+getName()+"] exception on transformation to get name", e); - } - } else { - requestedSessionKey = getSessionKey(); - } - TransformerPool pool = getTransformerPool(); - if (pool != null) { - try { - /* - * determine source for XSLT transformation from - * 1) value attribute - * 2) requestedSessionKey - * 3) pattern - * 4) input message - * - * N.B. this order differs from untransformed parameters - */ - Source source; - if (getValue() != null) { - source = XmlUtils.stringToSourceForSingleUse(getValue(), namespaceAware); - } else if (StringUtils.isNotEmpty(requestedSessionKey)) { - Object sourceObject = session.get(requestedSessionKey); - if (getType() == ParameterType.LIST && sourceObject instanceof List) { - // larva can produce the sourceObject as list - List items = (List) sourceObject; - XmlBuilder itemsXml = new XmlBuilder("items"); - for (String item : items) { - XmlBuilder itemXml = new XmlBuilder("item"); - itemXml.setValue(item); - itemsXml.addSubElement(itemXml); - } - source = XmlUtils.stringToSourceForSingleUse(itemsXml.toXML(), namespaceAware); - } else if (getType() == ParameterType.MAP && sourceObject instanceof Map) { - // larva can produce the sourceObject as map - Map items = (Map) sourceObject; - XmlBuilder itemsXml = new XmlBuilder("items"); - for (String item : items.keySet()) { - XmlBuilder itemXml = new XmlBuilder("item"); - itemXml.addAttribute("name", item); - itemXml.setValue(items.get(item)); - itemsXml.addSubElement(itemXml); - } - source = XmlUtils.stringToSourceForSingleUse(itemsXml.toXML(), namespaceAware); - } else { - Message sourceMsg = Message.asMessage(sourceObject); - if (StringUtils.isNotEmpty(getContextKey())) { - sourceMsg = Message.asMessage(sourceMsg.getContext().get(getContextKey())); - } - if (!sourceMsg.isEmpty()) { - LOG.debug("Parameter [{}] using sessionvariable [{}] as source for transformation", this::getName, () -> requestedSessionKey); - source = sourceMsg.asSource(); - } else { - LOG.debug("Parameter [{}] sessionvariable [{}] empty, no transformation will be performed", this::getName, () -> requestedSessionKey); - source = null; - } - } - } else if (StringUtils.isNotEmpty(getPattern())) { - String sourceString = formatPattern(alreadyResolvedParameters, session); - if (StringUtils.isNotEmpty(sourceString)) { - LOG.debug("Parameter [{}] using pattern [{}] as source for transformation", this::getName, this::getPattern); - source = XmlUtils.stringToSourceForSingleUse(sourceString, namespaceAware); - } else { - LOG.debug("Parameter [{}] pattern [{}] empty, no transformation will be performed", this::getName, this::getPattern); - source = null; - } - } else if (message != null) { - if (StringUtils.isNotEmpty(getContextKey())) { - source = Message.asMessage(message.getContext().get(getContextKey())).asSource(); - } else { - source = message.asSource(); - } - } else { - source = null; - } - if (source!=null) { - if (isRemoveNamespaces()) { - // TODO: There should be a more efficient way to do this - String rnResult = XmlUtils.removeNamespaces(XmlUtils.source2String(source)); - source = XmlUtils.stringToSource(rnResult); - } - ParameterValueList pvl = paramList == null ? null : paramList.getValues(message, session, namespaceAware); - switch (getType()) { - case NODE: - return transformToDocument(source, pvl).getFirstChild(); - case DOMDOC: - return transformToDocument(source, pvl); - default: - String transformResult = pool.transform(source, pvl); - if (StringUtils.isNotEmpty(transformResult)) { - result = transformResult; - } - break; - } - } - } catch (Exception e) { - throw new ParameterException(getName(), "Parameter ["+getName()+"] exception on transformation to get parametervalue", e); - } - } else { - /* - * No XSLT transformation, determine primary result from - * 1) requestedSessionKey - * 2) pattern - * 3) value attribute - * 4) input message - * - * N.B. this order differs from transformed parameters. - */ - if (StringUtils.isNotEmpty(requestedSessionKey)) { - result = session.get(requestedSessionKey); - if (result instanceof Message && StringUtils.isNotEmpty(getContextKey())) { - result = ((Message)result).getContext().get(getContextKey()); - } - if (LOG.isDebugEnabled() && (result == null || - ((result instanceof String) && ((String) result).isEmpty()) || - ((result instanceof Message) && ((Message) result).isEmpty()))) { - LOG.debug("Parameter [{}] session variable [{}] is empty", this::getName, () -> requestedSessionKey); - } - } else if (StringUtils.isNotEmpty(getPattern())) { - result = formatPattern(alreadyResolvedParameters, session); - } else if (getValue()!=null) { - result = getValue(); - } else { - try { - if (message==null) { - return null; - } - if (StringUtils.isNotEmpty(getContextKey())) { - result = message.getContext().get(getContextKey()); - } else { - message.preserve(); - result=message; - } - } catch (IOException e) { - throw new ParameterException(getName(), e); - } - } - } - - if (result instanceof Message) { //we just need to check if the message is null or not! - Message resultMessage = (Message) result; - if (Message.isNull(resultMessage)) { - result = null; - } else if (resultMessage.isRequestOfType(String.class)) { //Used by getMinLength and getMaxLength - try { - result = resultMessage.asString(); - } catch (IOException ignored) { - // Already checked for String, so this should never happen - } - } - } - if (result != null && !"".equals(result)) { - final Object finalResult = result; - LOG.debug("Parameter [{}] resolved to [{}]", this::getName, ()-> isHidden() ? hide(finalResult.toString()) : finalResult); - } else { - // if result is empty then return specified default value - Object valueByDefault=null; - Iterator it = getDefaultValueMethodsList().iterator(); - while (valueByDefault == null && it.hasNext()) { - DefaultValueMethods method = it.next(); - switch(method) { - case DEFAULTVALUE: - valueByDefault = getDefaultValue(); - break; - case SESSIONKEY: - valueByDefault = session.get(requestedSessionKey); - break; - case PATTERN: - valueByDefault = formatPattern(alreadyResolvedParameters, session); - break; - case VALUE: - valueByDefault = getValue(); - break; - case INPUT: - try { - message.preserve(); - valueByDefault=message.asString(); - } catch (IOException e) { - throw new ParameterException(getName(), e); - } - break; - default: - throw new IllegalArgumentException("Unknown defaultValues method ["+method+"]"); - } - } - if (valueByDefault!=null) { - result = valueByDefault; - final Object finalResult = result; - LOG.debug("Parameter [{}] resolved to default value [{}]", this::getName, ()-> isHidden() ? hide(finalResult.toString()) : finalResult); - } - } - if (result instanceof String) { - if (getMinLength()>=0 && getType()!=ParameterType.NUMBER) { - final String stringResult = (String) result; - if (stringResult.length() < getMinLength()) { - LOG.debug("Padding parameter [{}] because length [{}] falls short of minLength [{}]", this::getName, stringResult::length, this::getMinLength); - result = StringUtils.rightPad(stringResult, getMinLength()); - } - } - if (getMaxLength()>=0) { - final String stringResult = (String) result; - if (stringResult.length() > getMaxLength()) { - LOG.debug("Trimming parameter [{}] because length [{}] exceeds maxLength [{}]", this::getName, stringResult::length, this::getMaxLength); - result = stringResult.substring(0, getMaxLength()); - } - } - } - if(result !=null && getType().requiresTypeConversion) { - result = getValueAsType(result, namespaceAware); - } - if (result instanceof Number) { - if (getMinInclusiveString()!=null && ((Number)result).floatValue() < minInclusive.floatValue()) { - LOG.debug("Replacing parameter [{}] because value [{}] falls short of minInclusive [{}]", this::getName, logValue(result), this::getMinInclusiveString); - result = minInclusive; - } - if (getMaxInclusiveString()!=null && ((Number)result).floatValue() > maxInclusive.floatValue()) { - LOG.debug("Replacing parameter [{}] because value [{}] exceeds maxInclusive [{}]", this::getName, logValue(result), this::getMaxInclusiveString); - result = maxInclusive; - } - } - if (getType()==ParameterType.NUMBER && getMinLength()>=0 && (result+"").length()finalResult.getClass().getName(), ()-> finalResult); - } catch (DomBuilderException | IOException | XmlException e) { - throw new ParameterException(getName(), "Parameter ["+getName()+"] could not parse result ["+requestMessage+"] to XML nodeset",e); - } - break; - case DOMDOC: - try { - if (isRemoveNamespaces()) { - requestMessage = XmlUtils.removeNamespaces(requestMessage); - } - if(request instanceof Document) { - return request; - } - result = XmlUtils.buildDomDocument(requestMessage.asInputSource(), namespaceAware); - final Object finalResult = result; - LOG.debug("final result [{}][{}]", ()->finalResult.getClass().getName(), ()-> finalResult); - } catch (DomBuilderException | IOException | XmlException e) { - throw new ParameterException(getName(), "Parameter ["+getName()+"] could not parse result ["+requestMessage+"] to XML document",e); - } - break; - case DATE: - case DATETIME: - case TIMESTAMP: - case TIME: { - if (request instanceof Date) { - return request; - } - Message finalRequestMessage = requestMessage; - LOG.debug("Parameter [{}] converting result [{}] to Date using formatString [{}]", this::getName, () -> finalRequestMessage, this::getFormatString); - DateFormat df = new SimpleDateFormat(getFormatString()); - try { - result = df.parseObject(requestMessage.asString()); - } catch (ParseException e) { - throw new ParameterException(getName(), "Parameter [" + getName() + "] could not parse result [" + requestMessage + "] to Date using formatString [" + getFormatString() + "]", e); - } - break; - } - case XMLDATETIME: { - if (request instanceof Date) { - return request; - } - Message finalRequestMessage = requestMessage; - LOG.debug("Parameter [{}] converting result [{}] from XML dateTime to Date", this::getName, () -> finalRequestMessage); - result = XmlUtils.parseXmlDateTime(requestMessage.asString()); - break; - } - case NUMBER: { - if (request instanceof Number) { - return request; - } - Message finalRequestMessage = requestMessage; - LOG.debug("Parameter [{}] converting result [{}] to number decimalSeparator [{}] groupingSeparator [{}]", this::getName, ()->finalRequestMessage, decimalFormatSymbols::getDecimalSeparator, decimalFormatSymbols::getGroupingSeparator); - DecimalFormat decimalFormat = new DecimalFormat(); - decimalFormat.setDecimalFormatSymbols(decimalFormatSymbols); - try { - result = decimalFormat.parse(requestMessage.asString()); - } catch (ParseException e) { - throw new ParameterException(getName(), "Parameter [" + getName() + "] could not parse result [" + requestMessage + "] to number decimalSeparator [" + decimalFormatSymbols.getDecimalSeparator() + "] groupingSeparator [" + decimalFormatSymbols.getGroupingSeparator() + "]", e); - } - break; - } - case INTEGER: { - if (request instanceof Integer) { - return request; - } - Message finalRequestMessage = requestMessage; - LOG.debug("Parameter [{}] converting result [{}] to integer", this::getName, ()->finalRequestMessage); - try { - result = Integer.parseInt(requestMessage.asString()); - } catch (NumberFormatException e) { - throw new ParameterException(getName(), "Parameter [" + getName() + "] could not parse result [" + requestMessage + "] to integer", e); - } - break; - } - case BOOLEAN: { - if (request instanceof Boolean) { - return request; - } - Message finalRequestMessage = requestMessage; - LOG.debug("Parameter [{}] converting result [{}] to boolean", this::getName, ()->finalRequestMessage); - result = Boolean.parseBoolean(requestMessage.asString()); - break; - } - default: - break; - } - } catch(IOException e) { - throw new ParameterException(getName(), "Could not convert parameter ["+getName()+"] to String", e); - } - - return result; - } - - private String formatPattern(ParameterValueList alreadyResolvedParameters, PipeLineSession session) throws ParameterException { - int startNdx; - int endNdx = 0; - - // replace the named parameter with numbered parameters - StringBuilder formatPattern = new StringBuilder(); - List params = new ArrayList<>(); - int paramPosition = 0; - while(true) { - // get name of parameter in pattern to be substituted - startNdx = pattern.indexOf("{", endNdx); - if (startNdx == -1) { - formatPattern.append(pattern.substring(endNdx)); - break; - } - else { - formatPattern.append(pattern, endNdx, startNdx); - } - int tmpEndNdx = pattern.indexOf("}", startNdx); - endNdx = pattern.indexOf(",", startNdx); - if (endNdx == -1 || endNdx > tmpEndNdx) { - endNdx = tmpEndNdx; - } - if (endNdx == -1) { - throw new ParameterException(getName(), new ParseException("Bracket is not closed", startNdx)); - } - String substitutionPattern = pattern.substring(startNdx + 1, tmpEndNdx); - - // get value - Object substitutionValue = getValueForFormatting(alreadyResolvedParameters, session, substitutionPattern); - params.add(substitutionValue); - formatPattern.append('{').append(paramPosition++); - } - try { - return MessageFormat.format(formatPattern.toString(), params.toArray()); - } catch (Exception e) { - throw new ParameterException(getName(), "Cannot parse ["+formatPattern.toString()+"]", e); - } - } - - private Object preFormatDateType(Object rawValue, String formatType, String patternFormatString) throws ParameterException { - if (formatType!=null && (formatType.equalsIgnoreCase("date") || formatType.equalsIgnoreCase("time"))) { - if (rawValue instanceof Date) { - return rawValue; - } - DateFormat df = new SimpleDateFormat(StringUtils.isNotEmpty(patternFormatString) ? patternFormatString : DateFormatUtils.FORMAT_DATETIME_GENERIC); - try { - return df.parse(Message.asString(rawValue)); - } catch (ParseException | IOException e) { - throw new ParameterException(getName(), "Cannot parse ["+rawValue+"] as date", e); - } - } - if (rawValue instanceof Date) { - DateFormat df = new SimpleDateFormat(StringUtils.isNotEmpty(patternFormatString) ? patternFormatString : DateFormatUtils.FORMAT_DATETIME_GENERIC); - return df.format(rawValue); - } - try { - return Message.asString(rawValue); - } catch (IOException e) { - throw new ParameterException(getName(), "Cannot read date value ["+rawValue+"]", e); - } - } - - - private Object getValueForFormatting(ParameterValueList alreadyResolvedParameters, PipeLineSession session, String targetPattern) throws ParameterException { - String[] patternElements = targetPattern.split(","); - String name = patternElements[0].trim(); - String formatType = patternElements.length>1 ? patternElements[1].trim() : null; - String formatString = patternElements.length>2 ? patternElements[2].trim() : null; - - ParameterValue paramValue = alreadyResolvedParameters.get(name); - Object substitutionValue = paramValue == null ? null : paramValue.getValue(); - - if (substitutionValue == null) { - Object substitutionValueMessage = session.get(name); - if (substitutionValueMessage != null) { - if (substitutionValueMessage instanceof Date) { - substitutionValue = preFormatDateType(substitutionValueMessage, formatType, formatString); - } else { - if (substitutionValueMessage instanceof String) { - substitutionValue = substitutionValueMessage; - } else { - try { - Message message = Message.asMessage(substitutionValueMessage); // Do not close object from session here; might be reused later - substitutionValue = message.asString(); - } catch (IOException e) { - throw new ParameterException(getName(), "Cannot get substitution value from session key: " + name, e); - } - } - if (substitutionValue == null) throw new ParameterException(getName(), "Cannot get substitution value from session key: " + name); - } - } - } - if (substitutionValue == null) { - String namelc=name.toLowerCase(); - switch (namelc) { - case "now": - substitutionValue = preFormatDateType(new Date(), formatType, formatString); - break; - case "uid": - substitutionValue = UUIDUtil.createSimpleUUID(); - break; - case "uuid": - substitutionValue = UUIDUtil.createRandomUUID(); - break; - case "hostname": - substitutionValue = Misc.getHostname(); - break; - case "fixeddate": - if (!ConfigurationUtils.isConfigurationStubbed(configurationClassLoader)) { - throw new ParameterException(getName(), "Parameter pattern [" + name + "] only allowed in stub mode"); - } - Object fixedDateTime = session.get(PutSystemDateInSession.FIXEDDATE_STUB4TESTTOOL_KEY); - if (fixedDateTime == null) { - DateFormat df = new SimpleDateFormat(DateFormatUtils.FORMAT_DATETIME_GENERIC); - try { - fixedDateTime = df.parse(PutSystemDateInSession.FIXEDDATETIME); - } catch (ParseException e) { - throw new ParameterException(getName(), "Could not parse FIXEDDATETIME [" + PutSystemDateInSession.FIXEDDATETIME + "]", e); - } - } - substitutionValue = preFormatDateType(fixedDateTime, formatType, formatString); - break; - case "fixeduid": - if (!ConfigurationUtils.isConfigurationStubbed(configurationClassLoader)) { - throw new ParameterException(getName(), "Parameter pattern [" + name + "] only allowed in stub mode"); - } - substitutionValue = FIXEDUID; - break; - case "fixedhostname": - if (!ConfigurationUtils.isConfigurationStubbed(configurationClassLoader)) { - throw new ParameterException(getName(), "Parameter pattern [" + name + "] only allowed in stub mode"); - } - substitutionValue = FIXEDHOSTNAME; - break; - case "username": - substitutionValue = cf != null ? cf.getUsername() : ""; - break; - case "password": - substitutionValue = cf != null ? cf.getPassword() : ""; - break; - } - } - if (substitutionValue == null) { - if (isIgnoreUnresolvablePatternElements()) { - substitutionValue=""; - } else { - throw new ParameterException(getName(), "Parameter or session variable with name [" + name + "] in pattern [" + getPattern() + "] cannot be resolved"); - } - } - return substitutionValue; - } - - @Override - public String toString() { - return "Parameter name=[" + name + "] defaultValue=[" + defaultValue + "] sessionKey=[" + sessionKey + "] sessionKeyXPath=[" + sessionKeyXPath + "] xpathExpression=[" + xpathExpression + "] type=[" + type + "] value=[" + value + "]"; - } - - private TransformerPool getTransformerPool() { - return transformerPool; - } - - /** Name of the parameter */ - @Override - public void setName(String parameterName) { - name = parameterName; - } - @Override - public String getName() { - return name; - } - - /** The target data type of the parameter, related to the database or XSLT stylesheet to which the parameter is applied. */ - public void setType(ParameterType type) { - this.type = type; - } - - /** The value of the parameter, or the base for transformation using xpathExpression or stylesheet, or formatting. */ - public void setValue(String value) { - this.value = value; - } - - /** - * Key of a PipelineSession-variable.
If specified, the value of the PipelineSession variable is used as input for - * the xpathExpression or stylesheet, instead of the current input message.
If no xpathExpression or stylesheet are - * specified, the value itself is returned.
If the value '*' is specified, all existing sessionkeys are added as - * parameter of which the name starts with the name of this parameter.
If also the name of the parameter has the - * value '*' then all existing sessionkeys are added as parameter (except tsReceived) - */ - public void setSessionKey(String string) { - sessionKey = string; - } - - /** key of message context variable to use as source, instead of the message found from input message or sessionKey itself */ - public void setContextKey(String string) { - contextKey = string; - } - - /** Instead of a fixed sessionKey it's also possible to use a XPath expression applied to the input message to extract the name of the session-variable. */ - public void setSessionKeyXPath(String string) { - sessionKeyXPath = string; - } - - /** URL to a stylesheet that wil be applied to the contents of the message or the value of the session-variable. */ - public void setStyleSheetName(String stylesheetName){ - this.styleSheetName=stylesheetName; - } - - /** the XPath expression to extract the parameter value from the (xml formatted) input or session-variable. */ - public void setXpathExpression(String xpathExpression) { - this.xpathExpression = xpathExpression; - } - - /** - * If set to 2 or 3 a Saxon (net.sf.saxon) xslt processor 2.0 or 3.0 respectively will be used, otherwise xslt processor 1.0 (org.apache.xalan). 0 will auto-detect - * @ff.default 0 - */ - public void setXsltVersion(int xsltVersion) { - this.xsltVersion=xsltVersion; - } - - /** - * Namespace definitions for xpathExpression. Must be in the form of a comma or space separated list of - * prefix=namespaceuri-definitions. One entry can be without a prefix, that will define the default namespace. - */ - public void setNamespaceDefs(String namespaceDefs) { - this.namespaceDefs = namespaceDefs; - } - - /** - * When set true namespaces (and prefixes) in the input message are removed before the stylesheet/xpathExpression is executed - * @ff.default false - */ - public void setRemoveNamespaces(boolean b) { - removeNamespaces = b; - } - - /** If the result of sessionKey, xpathExpression and/or stylesheet returns null or an empty string, this value is returned */ - public void setDefaultValue(String string) { - defaultValue = string; - } - - /** - * Comma separated list of methods (defaultValue, sessionKey, pattern, value or input) to use as default value. Used in the order they appear until a non-null value is found. - * @ff.default defaultValue - */ - public void setDefaultValueMethods(String string) { - defaultValueMethods = string; - } - - /** - * Value of parameter is determined using substitution and formatting, following MessageFormat syntax with named parameters. The expression can contain references - * to session-variables or other parameters using the {name-of-parameter} and is formatted using java.text.MessageFormat. - *
NB: When referencing other parameters these MUST be defined before the parameter using pattern substitution. - *
- *
- * If for instance fname is a parameter or session-variable that resolves to Eric, then the pattern - * 'Hi {fname}, how do you do?' resolves to 'Hi Eric, do you do?'.
- * The following predefined reference can be used in the expression too:
    - *
  • {now}: the current system time
  • - *
  • {uid}: an unique identifier, based on the IP address and java.rmi.server.UID
  • - *
  • {uuid}: an unique identifier, based on the IP address and java.util.UUID
  • - *
  • {hostname}: the name of the machine the application runs on
  • - *
  • {username}: username from the credentials found using authAlias, or the username attribute
  • - *
  • {password}: password from the credentials found using authAlias, or the password attribute
  • - *
  • {fixeddate}: fake date, for testing only
  • - *
  • {fixeduid}: fake uid, for testing only
  • - *
  • {fixedhostname}: fake hostname, for testing only
  • - *
- * A guid can be generated using {hostname}_{uid}, see also - * http://java.sun.com/j2se/1.4.2/docs/api/java/rmi/server/uid.html for more information about (g)uid's or - * http://docs.oracle.com/javase/1.5.0/docs/api/java/util/uuid.html for more information about uuid's. - *
- * When combining a date or time pattern like {now} or {fixeddate} with a DATE, TIME, DATETIME or TIMESTAMP type, the effective value of the attribute - * formatString must match the effective value of the formatString in the pattern. - */ - public void setPattern(String string) { - pattern = string; - } - - /** Alias used to obtain username and password, used when a pattern containing {username} or {password} is specified */ - public void setAuthAlias(String string) { - authAlias = string; - } - - /** Default username that is used when a pattern containing {username} is specified */ - public void setUsername(String string) { - username = string; - } - - /** Default password that is used when a pattern containing {password} is specified */ - public void setPassword(String string) { - password = string; - } - - /** If set true pattern elements that cannot be resolved to a parameter or sessionKey are silently resolved to an empty string */ - public void setIgnoreUnresolvablePatternElements(boolean b) { - ignoreUnresolvablePatternElements = b; - } - - /** - * Used in combination with types DATE, TIME, DATETIME and TIMESTAMP to parse the raw parameter string data into an object of the respective type - * @ff.default depends on type - */ - public void setFormatString(String string) { - formatString = string; - } - - /** - * Used in combination with type NUMBER - * @ff.default system default - */ - public void setDecimalSeparator(String string) { - decimalSeparator = string; - } - - /** - * Used in combination with type NUMBER - * @ff.default system default - */ - public void setGroupingSeparator(String string) { - groupingSeparator = string; - } - - /** - * If set (>=0) and the length of the value of the parameter falls short of this minimum length, the value is padded - * @ff.default -1 - */ - public void setMinLength(int i) { - minLength = i; - } - - /** - * If set (>=0) and the length of the value of the parameter exceeds this maximum length, the length is trimmed to this maximum length - * @ff.default -1 - */ - public void setMaxLength(int i) { - maxLength = i; - } - - /** Used in combination with type number; if set and the value of the parameter exceeds this maximum value, this maximum value is taken */ - public void setMaxInclusive(String string) { - maxInclusiveString = string; - } - - /** Used in combination with type number; if set and the value of the parameter falls short of this minimum value, this minimum value is taken */ - public void setMinInclusive(String string) { - minInclusiveString = string; - } - - /** - * If set to true, the value of the parameter will not be shown in the log (replaced by asterisks) - * @ff.default false - */ - public void setHidden(boolean b) { - hidden = b; - } - - /** - * Set the mode of the parameter, which determines if the parameter is an INPUT, OUTPUT, or INOUT. - * This parameter only has effect for {@link StoredProcedureQuerySender}. - * An OUTPUT parameter does not need to have a value specified, but does need to have the type specified. - * Parameter values will not be updated, but output values will be put into the result of the - * {@link StoredProcedureQuerySender}. - * - * If not specified, the default is INPUT. - * - * @param mode INPUT, OUTPUT or INOUT. - */ - public void setMode(ParameterMode mode) { - this.mode = mode; - } -} \ No newline at end of file