aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorChristof Rabensteiner <christof.rabensteiner@iaik.tugraz.at>2019-07-22 13:02:19 +0200
committerChristof Rabensteiner <christof.rabensteiner@iaik.tugraz.at>2019-07-22 13:02:19 +0200
commitcb9a76eaafd37f921006822bcfe043655288bc63 (patch)
tree76c2463e181ac293134f4c5bfc7e342607f3f399 /src/main/java
parentd873625c0ced62e712dc1b1a7570b63482fd0a0a (diff)
downloadmoa-zs-cb9a76eaafd37f921006822bcfe043655288bc63.tar.gz
moa-zs-cb9a76eaafd37f921006822bcfe043655288bc63.tar.bz2
moa-zs-cb9a76eaafd37f921006822bcfe043655288bc63.zip
Test Flow of DeliveryRequest from "End-To-End" & Fix Bugs
Schema Changes: - Remove mzs:DeliveryRequest/TnvzMetaData because all metadata fields can be collected from DeliveryRequest and redundancy is not needed. Fixes and Refactoring in preprocess: - MzsDeliveryRequestValidator: Instead of returning false, throw an exception when a condition is not met, and explain which condition is not met / why it is not met in the exception's message. - Integrate interface change in ConfigProfileGenerator and DeliveryRequestAugmenter. - Rewrite and simplify DeliveryRequestAugmenter's augmentation. - ConfigUtil Fixes: Ensure that we do not override the wrong parameters while merging. This error appeared in tnvz / msg client, connection / receive timeout, key / trust store, and lax hostname verification / trust all. Fix Bugs in Interceptor / SoapUtils: - Problem: DOM access and information extraction was implemented somewhat sloppy. - SolutioN: Change DOM access interface to access DOM more efficiently. Add boundary checks and handle edge cases while extracting information from SOAP Messages. - Test those changes properly. Testing: - Implement Delivery Request Flow in ITEndToEndTest. - Start application on random port instead of fixed port when running integration tests. - Add assertions to tests in ITMzsServiceTest suite. Others Bug Fixes: - ServicesConfig: Ensure that mzs service and msg service run on different endpoint addresses (/msg and /mzs). - DeliveryRequestBackend: Throw exception when binary message is missing. Don't wrap the exception. - SaveResponseToFileSink: Wrap Response in JAXB Element (otherwise, marshaller does not recognize it)
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/at/gv/egiz/moazs/backend/DeliveryRequestBackend.java13
-rw-r--r--src/main/java/at/gv/egiz/moazs/backend/SaveResponseToFileSink.java2
-rw-r--r--src/main/java/at/gv/egiz/moazs/client/TnvzHelper.java8
-rw-r--r--src/main/java/at/gv/egiz/moazs/config/ServicesConfig.java7
-rw-r--r--src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java8
-rw-r--r--src/main/java/at/gv/egiz/moazs/preprocess/ConfigUtil.java9
-rw-r--r--src/main/java/at/gv/egiz/moazs/preprocess/DeliveryRequestAugmenter.java70
-rw-r--r--src/main/java/at/gv/egiz/moazs/preprocess/MzsDeliveryRequestValidator.java160
-rw-r--r--src/main/java/at/gv/egiz/moazs/repository/InMemoryDeliveryRepository.java15
-rw-r--r--src/main/java/at/gv/egiz/moazs/scheme/Marshaller.java4
-rw-r--r--src/main/java/at/gv/egiz/moazs/scheme/NameSpace.java5
-rw-r--r--src/main/java/at/gv/egiz/moazs/scheme/SOAPUtils.java64
-rw-r--r--src/main/java/at/gv/egiz/moazs/util/EndpointFactory.java8
-rw-r--r--src/main/java/at/gv/egiz/moazs/util/StoreSOAPBodyBinaryInRepositoryInterceptor.java20
14 files changed, 267 insertions, 126 deletions
diff --git a/src/main/java/at/gv/egiz/moazs/backend/DeliveryRequestBackend.java b/src/main/java/at/gv/egiz/moazs/backend/DeliveryRequestBackend.java
index 6a1e0fd..72f8ba0 100644
--- a/src/main/java/at/gv/egiz/moazs/backend/DeliveryRequestBackend.java
+++ b/src/main/java/at/gv/egiz/moazs/backend/DeliveryRequestBackend.java
@@ -18,10 +18,10 @@ import org.springframework.stereotype.Component;
import java.util.function.Consumer;
-import static at.gv.egiz.moazs.scheme.RequestStatusResponse.*;
+import static at.gv.egiz.moazs.MoaZSException.moaZSException;
import static at.gv.egiz.moazs.scheme.RequestStatusResponse.generateError;
+import static at.gv.egiz.moazs.scheme.RequestStatusResponse.getAnswer;
import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.Error.errorBuilder;
-import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.deliveryRequestStatusTypeBuilder;
import static java.lang.String.format;
@Component
@@ -72,7 +72,7 @@ public class DeliveryRequestBackend implements Consumer<String> {
try {
var mzsRequest = repository.retrieveDeliveryRequest(appDeliveryID).orElseThrow(
- () -> MoaZSException.moaZSException(format(DELIVERY_REQUEST_MISSING_ERROR_MSG, appDeliveryID)));
+ () -> moaZSException(format(DELIVERY_REQUEST_MISSING_ERROR_MSG, appDeliveryID)));
fallbackAnswerBuilder.withDeliverySystem(mzsRequest.getConfig().getMSGClient().getURL());
var msgRequest = buildMsgRequest(mzsRequest);
@@ -98,14 +98,15 @@ public class DeliveryRequestBackend implements Consumer<String> {
}
private void verifySignedStatus(String responseID, String appDeliveryID) throws MoaZSException {
+ var signedStatus = repository.retrieveBinaryResponse(responseID).orElseThrow(() -> moaZSException(
+ format(BINARY_RESPONSE_MISSING_ERROR_MSG, responseID),
+ MoaZSException.ERROR_MZS_BINARY_RESPONSE_MISSING));
try {
- var signedStatus = repository.retrieveBinaryResponse(responseID).orElseThrow(
- () -> MoaZSException.moaZSException(format(BINARY_RESPONSE_MISSING_ERROR_MSG, responseID)));
signatureVerifier.accept(signedStatus);
} catch (MoaZSException ex) {
var message = format(MsgResponseBackend.MOASP_SIGNATURE_INVALID_ERROR_MSG, appDeliveryID);
var code = MoaZSException.ERROR_MOASP_SIGNATURE_INVALID;
- throw MoaZSException.moaZSException(message, code, ex);
+ throw moaZSException(message, code, ex);
}
}
diff --git a/src/main/java/at/gv/egiz/moazs/backend/SaveResponseToFileSink.java b/src/main/java/at/gv/egiz/moazs/backend/SaveResponseToFileSink.java
index 2468ca9..c58e1a5 100644
--- a/src/main/java/at/gv/egiz/moazs/backend/SaveResponseToFileSink.java
+++ b/src/main/java/at/gv/egiz/moazs/backend/SaveResponseToFileSink.java
@@ -50,7 +50,7 @@ public class SaveResponseToFileSink {
var responseID = response.getResponseID();
var responsePath = generatePath(rootPath, responseID, "xml");
- var storeResponseToFileSystemFuture = supplyAsync(() -> msgMarshaller.marshallXml(response.getResponse()))
+ var storeResponseToFileSystemFuture = supplyAsync(() -> msgMarshaller.marshallXml(response.getResponseAsJAXBElement()))
.thenApply(responseString -> responseString.getBytes(StandardCharsets.UTF_8))
.thenAccept(responseByteArray -> storeToFile(responsePath, responseByteArray))
.exceptionally(ex -> logException(ex, responseID));
diff --git a/src/main/java/at/gv/egiz/moazs/client/TnvzHelper.java b/src/main/java/at/gv/egiz/moazs/client/TnvzHelper.java
index de22805..a304bdf 100644
--- a/src/main/java/at/gv/egiz/moazs/client/TnvzHelper.java
+++ b/src/main/java/at/gv/egiz/moazs/client/TnvzHelper.java
@@ -96,18 +96,16 @@ public class TnvzHelper {
var builder = metaDataBuilder();
- var meta = request.getTnvzMetaData();
-
+ var meta = request.getMetaData();
if (meta.getDeliveryQuality() != null) {
builder.withDeliveryQuality(meta.getDeliveryQuality());
} else {
builder.withPrivateMessageQuality(meta.getPrivateMessageQuality());
}
- return builder
- .withOrigin(meta.getOrigin())
- .withPreAdviceNote(request.getReceiver().getPreAdviceNote())
+ return builder.withOrigin(meta.getOrigin())
.withIgnorePostRedirectionOrder(meta.getIgnorePostRedirectionOrder())
+ .withPreAdviceNote(request.getReceiver().getPreAdviceNote())
.build();
}
diff --git a/src/main/java/at/gv/egiz/moazs/config/ServicesConfig.java b/src/main/java/at/gv/egiz/moazs/config/ServicesConfig.java
index c16dfd2..6f71e50 100644
--- a/src/main/java/at/gv/egiz/moazs/config/ServicesConfig.java
+++ b/src/main/java/at/gv/egiz/moazs/config/ServicesConfig.java
@@ -23,14 +23,15 @@ public class ServicesConfig {
@Autowired
public Endpoint msgEndpoint(MsgService msgService,
Zuse2AppPortService zuse2app,
- Interceptor<Message> msgInterceptor) {
- return endpointFactory.create(msgService, zuse2app, msgInterceptor);
+ Interceptor<Message> msgInterceptor
+ ) {
+ return endpointFactory.create(msgService, zuse2app, "/msg", msgInterceptor);
}
@Bean
@Autowired
public Endpoint mzsEndpoint(MzsService mzsService, App2Mzs app2mzs) {
- return endpointFactory.create(mzsService, app2mzs);
+ return endpointFactory.create(mzsService, app2mzs, "/mzs");
}
@Bean
diff --git a/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java b/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java
index 5e81f0d..0637f98 100644
--- a/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java
+++ b/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java
@@ -11,6 +11,8 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import static at.gv.egiz.moazs.MoaZSException.moaZSException;
+import static java.lang.String.format;
import static java.util.stream.Collectors.*;
public class ConfigProfileGenerator {
@@ -70,9 +72,11 @@ public class ConfigProfileGenerator {
var defaultProfile = profiles.get(defaultConfigKey);
- if (!validator.isConfigProfileComplete(defaultProfile)) {
+ try {
+ validator.isConfigProfileComplete(defaultProfile);
+ } catch (MoaZSException ex) {
if (verifyCompletenessOfDefaultConfiguration)
- throw MoaZSException.moaZSException(PROFILE_NOT_COMPLETE_ERROR_MESSAGE);
+ throw moaZSException(format("%s Reason: %s", PROFILE_NOT_COMPLETE_ERROR_MESSAGE, ex.getMessage()));
else {
LOGGER.warn(PROFILE_NOT_COMPLETE_WARNING_MESSAGE);
}
diff --git a/src/main/java/at/gv/egiz/moazs/preprocess/ConfigUtil.java b/src/main/java/at/gv/egiz/moazs/preprocess/ConfigUtil.java
index 056f6dc..f49132f 100644
--- a/src/main/java/at/gv/egiz/moazs/preprocess/ConfigUtil.java
+++ b/src/main/java/at/gv/egiz/moazs/preprocess/ConfigUtil.java
@@ -205,7 +205,7 @@ public class ConfigUtil {
}
if (primary.getTNVZClient() != null) {
- builder.withMSGClient(merge(primary.getTNVZClient(), fallback.getTNVZClient()));
+ builder.withTNVZClient(merge(primary.getTNVZClient(), fallback.getTNVZClient()));
}
if (primary.getMsgResponseSinks() != null) {
@@ -240,7 +240,7 @@ public class ConfigUtil {
}
if (primary.getReceiveTimeout() != null) {
- builder.withConnectionTimeout(primary.getReceiveTimeout());
+ builder.withReceiveTimeout(primary.getReceiveTimeout());
}
return builder.build();
@@ -259,7 +259,7 @@ public class ConfigUtil {
}
if (primary.getTrustStore() != null) {
- builder.withKeyStore(merge(primary.getTrustStore(), fallback.getTrustStore()));
+ builder.withTrustStore(merge(primary.getTrustStore(), fallback.getTrustStore()));
}
if (primary.isLaxHostNameVerification() != null) {
@@ -267,8 +267,9 @@ public class ConfigUtil {
}
if (primary.isTrustAll() != null) {
- builder.withLaxHostNameVerification(primary.isTrustAll());
+ builder.withTrustAll(primary.isTrustAll());
}
+
return builder.build();
}
diff --git a/src/main/java/at/gv/egiz/moazs/preprocess/DeliveryRequestAugmenter.java b/src/main/java/at/gv/egiz/moazs/preprocess/DeliveryRequestAugmenter.java
index e7ee357..240a677 100644
--- a/src/main/java/at/gv/egiz/moazs/preprocess/DeliveryRequestAugmenter.java
+++ b/src/main/java/at/gv/egiz/moazs/preprocess/DeliveryRequestAugmenter.java
@@ -1,36 +1,41 @@
package at.gv.egiz.moazs.preprocess;
+import at.gv.egiz.moazs.scheme.Marshaller;
import at.gv.zustellung.app2mzs.xsd.ConfigType;
import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType;
+import at.gv.zustellung.app2mzs.xsd.ObjectFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import java.util.Map;
import static at.gv.egiz.moazs.MoaZSException.moaZSException;
+import static at.gv.egiz.moazs.util.NullCoalesce.coalesce;
import static at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.deliveryRequestTypeBuilder;
-import static java.lang.String.format;
@Component
public class DeliveryRequestAugmenter {
+ private static final Logger log = LoggerFactory.getLogger(DeliveryRequestAugmenter.class);
+ private static final ObjectFactory FACTORY = new ObjectFactory();
+
private final ConfigUtil util;
private final Map<String, ConfigType> configs;
private final MzsDeliveryRequestValidator validator;
+ private final Marshaller mzsMarshaller;
- private static final String INCOMPLETE_TNVZ_ERROR_MESSAGE = "mzs:DeliveryRequest is incomplete because mandatory " +
- "fields for sending a tnvz:QueryPersonRequest are missing.";
- private static final String INCOMPLETE_CONFIG_ERROR_MESSAGE = "Could not find a profile for " +
- "the delivery request configuration, and the configuration attached to mzs:DeliveryRequest is incomplete.";
- private static final String INCOMPLETE_MERGED_CONFIG_ERROR_MESSAGE = "I merged parameters from " +
- "mzs:DeliveryRequest/Config with parameters from config profile with ProfileId='%s', but the " +
- "configuration is incomplete.";
+ private static final String CONFIG_MISSING_ERROR_MSG = "Delivery request configuration is missing.";
@Autowired
- public DeliveryRequestAugmenter(Map<String, ConfigType> deliveryRequestConfigs, ConfigUtil util, MzsDeliveryRequestValidator validator) {
+ public DeliveryRequestAugmenter(Map<String, ConfigType> deliveryRequestConfigs, ConfigUtil util,
+ MzsDeliveryRequestValidator validator, Marshaller mzsMarshaller) {
this.configs = deliveryRequestConfigs;
this.util = util;
this.validator = validator;
+ this.mzsMarshaller = mzsMarshaller;
}
/**
@@ -46,41 +51,29 @@ public class DeliveryRequestAugmenter {
var fallbackProfileId = determineProfileIdFrom(requestConfig);
var fallbackConfig = configs.get(fallbackProfileId);
- if (fallbackConfig == null) {
-
- if (!validator.isConfigProfileComplete(request.getConfig())) {
- throw moaZSException(INCOMPLETE_CONFIG_ERROR_MESSAGE);
- } else if (!validator.isTnvzComplete(request)) {
- throw moaZSException(INCOMPLETE_TNVZ_ERROR_MESSAGE);
- } else {
- return request;
- }
+ trace("request config", requestConfig);
+ trace("fallback config", fallbackConfig);
- } else {
+ var augmentedConfig = (requestConfig != null && fallbackConfig != null)
+ ? util.merge(requestConfig, fallbackConfig)
+ : coalesce(requestConfig, fallbackConfig)
+ .orElseThrow(()-> moaZSException(CONFIG_MISSING_ERROR_MSG));
- var mergedConfig = (requestConfig == null)
- ? fallbackConfig
- : util.merge(requestConfig, fallbackConfig);
+ trace("augmented config", augmentedConfig);
- if (!validator.isConfigProfileComplete(mergedConfig)) {
- var message = format(INCOMPLETE_MERGED_CONFIG_ERROR_MESSAGE, fallbackProfileId);
- throw moaZSException(message);
- }
+ validator.isConfigProfileComplete(augmentedConfig);
- var mergedRequest = deliveryRequestTypeBuilder(request)
- .withConfig(mergedConfig)
- .build();
+ var augmentedRequest = deliveryRequestTypeBuilder(request)
+ .withConfig(augmentedConfig)
+ .build();
- if (!validator.isTnvzComplete(mergedRequest)) {
- throw moaZSException(INCOMPLETE_TNVZ_ERROR_MESSAGE);
- }
+ validator.isTnvzComplete(augmentedRequest);
- return mergedRequest;
+ return augmentedRequest;
- }
}
- private String determineProfileIdFrom(ConfigType requestConfig) {
+ private String determineProfileIdFrom(@Nullable ConfigType requestConfig) {
return (requestConfig == null
|| requestConfig.getProfileID() == null
|| isProfileMissing(requestConfig.getProfileID()))
@@ -92,4 +85,11 @@ public class DeliveryRequestAugmenter {
return !configs.containsKey(id);
}
+ private void trace(String description, ConfigType config) {
+ if (log.isTraceEnabled()) {
+ log.trace("{} : {}", description, mzsMarshaller.marshallXml(FACTORY.createConfig(config)));
+ }
+ }
+
+
}
diff --git a/src/main/java/at/gv/egiz/moazs/preprocess/MzsDeliveryRequestValidator.java b/src/main/java/at/gv/egiz/moazs/preprocess/MzsDeliveryRequestValidator.java
index 2c2fc36..67086a2 100644
--- a/src/main/java/at/gv/egiz/moazs/preprocess/MzsDeliveryRequestValidator.java
+++ b/src/main/java/at/gv/egiz/moazs/preprocess/MzsDeliveryRequestValidator.java
@@ -1,90 +1,168 @@
package at.gv.egiz.moazs.preprocess;
+import at.gv.egiz.moazs.MoaZSException;
import at.gv.zustellung.app2mzs.xsd.*;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
+import static at.gv.egiz.moazs.MoaZSException.moaZSException;
+import static at.gv.egiz.moazs.scheme.NameSpace.*;
+import static java.lang.String.format;
+
@Component
public class MzsDeliveryRequestValidator {
/**
* Checks if the mandatory fields that are needed to send a tnvz:QueryPersonRequest are present.
* @param request
- * @return true if mandatory fields are present.
+ * @throws MoaZSException if a field is missing.
*/
- public boolean isTnvzComplete(DeliveryRequestType request) {
- return !request.getConfig().isPerformQueryPersonRequest() ||
- (request.getTnvzMetaData() != null
- && request.getSender().getCorporateBody() != null);
+ public void isTnvzComplete(DeliveryRequestType request) {
+ if (request.getConfig().isPerformQueryPersonRequest()) {
+
+ if (request.getMetaData().getOrigin() == null)
+ throw mzse(MZS_DELIVERY_REQUEST, MZS_DELIVERY_REQUEST + "/MetaData/Origin is missing.");
+
+ if (request.getMetaData().getDeliveryQuality() == null)
+ throw mzse(MZS_DELIVERY_REQUEST, MZS_DELIVERY_REQUEST + "/MetaData/DeliveryQuality missing.");
+
+ if (request.getSender().getCorporateBody() == null)
+ throw mzse(MZS_DELIVERY_REQUEST, MZS_DELIVERY_REQUEST + "/Sender/CorporateBody is missing.");
+ }
}
/**
* Check if all mandatory fields of configuration are present.
*
* @param profile
- * @return true if all mandatory fields are present.
+ * @throws MoaZSException if a field is missing.
*/
- public boolean isConfigProfileComplete(@Nullable ConfigType profile) {
- return profile != null
- && profile.isPerformQueryPersonRequest() != null
- && isTVNZClientConfigured(profile.getTNVZClient(), profile.isPerformQueryPersonRequest())
- && isClientConfigured(profile.getMSGClient())
- && areSinksConfigured(profile.getMsgResponseSinks());
+ public void isConfigProfileComplete(@Nullable ConfigType profile) {
+
+ if (profile == null)
+ throw mzse(MZS_DELIVERY_REQUEST + "/Config");
+
+ if (profile.isPerformQueryPersonRequest() == null)
+ throw mzse(MZS_DELIVERY_REQUEST + "/Config", "PerformQueryPersonRequest is missing.");
+
+ isTNVZClientConfigured(profile.getTNVZClient(), profile.isPerformQueryPersonRequest());
+ areSinksConfigured(profile.getMsgResponseSinks());
+
+ try {
+ isClientConfigured(profile.getMSGClient());
+ } catch (MoaZSException ex) {
+ throw mzse(MZS_MSGCLIENT, ex.getMessage());
+ }
+
}
- private boolean isTVNZClientConfigured(ClientType tnvzClient, Boolean isPerformQueryPersonRequest) {
- return !isPerformQueryPersonRequest || (tnvzClient != null
+ private void isTNVZClientConfigured(@Nullable ClientType tnvzClient, Boolean isPerformQueryPersonRequest) {
+ if (!isPerformQueryPersonRequest) return;
+
+ var isConfigured = tnvzClient != null
&& tnvzClient.getURL() != null
&& tnvzClient.getReceiveTimeout() != null
- && tnvzClient.getConnectionTimeout() != null
- && isSSLConfigured(tnvzClient));
+ && tnvzClient.getConnectionTimeout() != null;
+
+ if (!isConfigured) {
+ if(tnvzClient == null) throw mzse(MZS_TNVZCLIENT);
+
+ var reasons = new StringBuilder("The following elements in " + MZS_TNVZCLIENT + " are missing: ");
+ if(tnvzClient.getURL() == null) reasons.append("URL;");
+ if(tnvzClient.getReceiveTimeout() == null) reasons.append("ReceiveTimeout;");
+ if(tnvzClient.getConnectionTimeout() == null) reasons.append("ConnectionTimeout;");
+ throw mzse(MZS_TNVZCLIENT, reasons.toString());
+ }
+
+ try {
+ isSSLConfigured(tnvzClient);
+ } catch (MoaZSException ex) {
+ throw mzse(MZS_TNVZCLIENT, ex.getMessage());
+ }
}
- private boolean isClientConfigured(ClientType clientParams) {
- return clientParams != null
+ private void isClientConfigured(@Nullable ClientType clientParams) {
+ var isConfigured = clientParams != null
&& clientParams.getURL() != null
- && isSSLConfigured(clientParams)
&& clientParams.getReceiveTimeout() != null
&& clientParams.getConnectionTimeout() != null;
+
+ if (!isConfigured) throw mzse("Client");
+
+ isSSLConfigured(clientParams);
+
}
- private boolean isSSLConfigured(ClientType clientParams) {
- return !clientParams.getURL().startsWith("https") || (clientParams.getSSL() != null
- && clientParams.getSSL().isTrustAll() != null
- && clientParams.getSSL().isLaxHostNameVerification() != null
- && isKeyStoreConfigured(clientParams.getSSL().getKeyStore())
- && isTrustStoreConfigured(clientParams.getSSL().getTrustStore()));
+ private void isSSLConfigured(ClientType clientParams) {
+ if (!clientParams.getURL().startsWith("https")) return;
+
+ var isConfigured = (clientParams.getSSL() != null
+ && clientParams.getSSL().isTrustAll() != null
+ && clientParams.getSSL().isLaxHostNameVerification() != null);
+ if (!isConfigured) throw mzse("SSL");
+
+ try {
+ isKeyStoreConfigured(clientParams.getSSL().getKeyStore());
+ isTrustStoreConfigured(clientParams.getSSL().getTrustStore());
+ } catch (MoaZSException ex) {
+ throw mzse("SSL", ex.getMessage());
+ }
}
- private boolean isKeyStoreConfigured(KeyStoreType keyStore) {
- return keyStore == null || (keyStore.getPassword() != null
+ private void isKeyStoreConfigured(@Nullable KeyStoreType keyStore) {
+ if (keyStore == null) return;
+
+ var isConfigured = keyStore.getPassword() != null
&& keyStore.getFileType() != null
- && keyStore.getFileName() != null);
+ && keyStore.getFileName() != null;
+ if (!isConfigured) throw mzse("KeyStore");
}
- private boolean isTrustStoreConfigured(KeyStoreType trustStore) {
- return trustStore == null || (trustStore.getPassword() != null
+ private void isTrustStoreConfigured(@Nullable KeyStoreType trustStore) {
+ if (trustStore == null) return;
+
+ var isConfigured = trustStore.getPassword() != null
&& "JKS".equals(trustStore.getFileType())
- && trustStore.getFileName() != null);
+ && trustStore.getFileName() != null;
+ if (!isConfigured) throw mzse("TrustStore");
}
- private boolean areSinksConfigured(MsgResponseSinksType sinks) {
- return sinks != null
- && sinks.isLogResponse() != null
- && isSaveResponseToFileConfigured(sinks.getSaveResponseToFile())
- && isForwardResponseToServiceConfigured(sinks.getForwardResponseToService());
+ private void areSinksConfigured(@Nullable MsgResponseSinksType sinks) {
+ var isConfigured = sinks != null && sinks.isLogResponse() != null;
+ if (!isConfigured) throw mzse("MsgResponseSinks");
+
+ isSaveResponseToFileConfigured(sinks.getSaveResponseToFile());
+ isForwardResponseToServiceConfigured(sinks.getForwardResponseToService());
}
- private boolean isSaveResponseToFileConfigured(SaveResponseToFileType fileSink) {
- return fileSink != null
+ private void isSaveResponseToFileConfigured(@Nullable SaveResponseToFileType fileSink) {
+ var isConfigured = fileSink != null
&& (!fileSink.isActive() || fileSink.getPath() != null);
+
+ if (!isConfigured) throw mzse("SaveResponseToFile");
+ }
+
+ private void isForwardResponseToServiceConfigured(@Nullable ForwardResponseToServiceType forwardSink) {
+ if (forwardSink == null) throw mzse("ForwardResponseToService");
+
+ if (forwardSink.isActive()) {
+ try {
+ isClientConfigured(forwardSink.getMzsClient());
+ } catch (MoaZSException e) {
+ throw mzse("ForwardResponseToService", e.getMessage());
+ }
+ }
}
- private boolean isForwardResponseToServiceConfigured(ForwardResponseToServiceType forwardSink) {
- return forwardSink != null
- && (!forwardSink.isActive() || isClientConfigured(forwardSink.getMzsClient()));
+ private MoaZSException mzse(String missing) {
+ return moaZSException(format("%s is not configured.", missing));
}
+ private MoaZSException mzse(String missing, String reason) {
+ return moaZSException(format("%s is not configured. Reason: %s", missing, reason));
+ }
+
+
}
diff --git a/src/main/java/at/gv/egiz/moazs/repository/InMemoryDeliveryRepository.java b/src/main/java/at/gv/egiz/moazs/repository/InMemoryDeliveryRepository.java
index 41b742b..b8a6d78 100644
--- a/src/main/java/at/gv/egiz/moazs/repository/InMemoryDeliveryRepository.java
+++ b/src/main/java/at/gv/egiz/moazs/repository/InMemoryDeliveryRepository.java
@@ -4,6 +4,8 @@ package at.gv.egiz.moazs.repository;
import at.gv.egiz.moazs.scheme.MsgResponse;
import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType;
import com.google.common.cache.Cache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Repository;
@@ -17,6 +19,8 @@ import static java.util.Optional.ofNullable;
@Profile("!cluster")
public class InMemoryDeliveryRepository implements DeliveryRepository {
+ private static final Logger log = LoggerFactory.getLogger(InMemoryDeliveryRepository.class);
+
private final Cache<String, DeliveryRequestType> requestRepository;
private final Cache<String, MsgResponse> responseRepository;
private final Cache<String, byte[]> binaryResponseRepository;
@@ -31,33 +35,38 @@ public class InMemoryDeliveryRepository implements DeliveryRepository {
@Override
public void store(DeliveryRequestType request) {
var key = request.getMetaData().getAppDeliveryID();
+ log.trace("Store DeliveryRequest by key={}", key);
requestRepository.put(key, request);
}
@Override
public Optional<DeliveryRequestType> retrieveDeliveryRequest(String appDeliveryID) {
+ log.trace("Retrieve DeliveryRequest by key={}", appDeliveryID);
return ofNullable(requestRepository.getIfPresent(appDeliveryID));
}
@Override
public void store(MsgResponse response) {
String key = response.getResponseID();
+ log.trace("Store MsgResponse by key={}", key);
responseRepository.put(key, response);
}
@Override
public Optional<MsgResponse> retrieveResponse(String responseID) {
+ log.trace("Retrieve MsgResponse by key={}", responseID);
return ofNullable(responseRepository.getIfPresent(responseID));
}
@Override
- public void store(String id, byte[] data) {
- binaryResponseRepository.put(id, data);
-
+ public void store(String responseID, byte[] data) {
+ log.trace("Store Binary MsgResponse by key={}", responseID);
+ binaryResponseRepository.put(responseID, data);
}
@Override
public Optional<byte[]> retrieveBinaryResponse(String responseID) {
+ log.trace("Retrieve Binary MsgResponse by key={}", responseID);
return ofNullable(binaryResponseRepository.getIfPresent(responseID));
}
diff --git a/src/main/java/at/gv/egiz/moazs/scheme/Marshaller.java b/src/main/java/at/gv/egiz/moazs/scheme/Marshaller.java
index 83ace5c..1a86079 100644
--- a/src/main/java/at/gv/egiz/moazs/scheme/Marshaller.java
+++ b/src/main/java/at/gv/egiz/moazs/scheme/Marshaller.java
@@ -32,6 +32,10 @@ public class Marshaller {
}
public <T> String marshallXml(final T obj) {
+ if (obj == null) {
+ return "null";
+ }
+
StringWriter sw = new StringWriter();
Result result = new StreamResult(sw);
jaxbMarshaller.marshal(obj, result);
diff --git a/src/main/java/at/gv/egiz/moazs/scheme/NameSpace.java b/src/main/java/at/gv/egiz/moazs/scheme/NameSpace.java
index 6b6f34a..386a7a6 100644
--- a/src/main/java/at/gv/egiz/moazs/scheme/NameSpace.java
+++ b/src/main/java/at/gv/egiz/moazs/scheme/NameSpace.java
@@ -5,6 +5,7 @@ public class NameSpace {
private NameSpace() {}
private static final at.gv.zustellung.msg.xsd.ObjectFactory MSG_FACTORY = new at.gv.zustellung.msg.xsd.ObjectFactory();
+ private static final at.gv.zustellung.app2mzs.xsd.ObjectFactory MZS_FACTORY = new at.gv.zustellung.app2mzs.xsd.ObjectFactory();
public static final String MSG_VERSION = "2.2.0";
public static final String MSG = MSG_FACTORY.createDeliveryRequest(null).getName().getNamespaceURI();
@@ -18,4 +19,8 @@ public class NameSpace {
public static final String MSG_DELIVERY_NOTIFICATION = MSG_FACTORY.createDeliveryNotification(null).getName().getLocalPart();
public static final String MSG_APP_DELIVERY_ID = MSG_FACTORY.createAppDeliveryID("").getName().getLocalPart();
+ public static final String MZS_DELIVERY_REQUEST = MZS_FACTORY.createDeliveryRequest(null).getName().getLocalPart();
+ public static final String MZS_TNVZCLIENT = MZS_FACTORY.createTNVZClient(null).getName().getLocalPart();
+ public static final String MZS_MSGCLIENT = MZS_FACTORY.createTNVZClient(null).getName().getLocalPart();
+
}
diff --git a/src/main/java/at/gv/egiz/moazs/scheme/SOAPUtils.java b/src/main/java/at/gv/egiz/moazs/scheme/SOAPUtils.java
index 6e96a6b..461d8fe 100644
--- a/src/main/java/at/gv/egiz/moazs/scheme/SOAPUtils.java
+++ b/src/main/java/at/gv/egiz/moazs/scheme/SOAPUtils.java
@@ -3,8 +3,12 @@ package at.gv.egiz.moazs.scheme;
import at.gv.egiz.eaaf.core.impl.utils.DOMUtils;
import at.gv.egiz.moazs.MoaZSException;
import org.apache.cxf.binding.soap.Soap11;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
@@ -12,34 +16,72 @@ import javax.xml.transform.TransformerException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.LinkedList;
+import java.util.List;
+
+import static at.gv.egiz.moazs.MoaZSException.moaZSException;
@Component
public class SOAPUtils {
+ private static final Logger log = LoggerFactory.getLogger(SOAPUtils.class);
+ private static final String SOAP_BODY_MISSING_ERROR_MSG = "<soap11:Body> is missing.";
+ private static final String SOAP_BODY_CHILDREN_MISSING_ERROR_MSG = "<soap11:Body> has no child elements.";
+ private static final String APP_DELIVERY_ID_MISSING_ERROR_MSG = "<msg:AppDeliveryID> is missing.";
+ private static final String APP_DELIVERY_ID_EMPTY_ERROR_MSG = "<msg:AppDeliveryID> is empty.";
+ private static final String MULTIPLE_MSG = "Found multiple {} elements. Will choose first element.";
+ private static final String APP_DELIVERY_ID_FULL_TAG_NAME = "<msg:" + NameSpace.MSG_APP_DELIVERY_ID + ">";
+
public Element toDOM(byte[] bytes) throws IOException, SAXException, ParserConfigurationException {
var stream = new ByteArrayInputStream(bytes);
return DOMUtils.parseXmlNonValidating(stream);
}
- public byte[] unwrapSoapEnvelope(Element document) {
- try {
- var body = document.getElementsByTagNameNS(Soap11.SOAP_NAMESPACE, "Body");
- var item = body.item(0).getFirstChild();
+ public Node getChildElementOfSoapBody(Element document) throws MoaZSException {
+
+ var bodyList = document.getElementsByTagNameNS(Soap11.SOAP_NAMESPACE, "Body");
+ if (bodyList.getLength() == 0) throw moaZSException(SOAP_BODY_MISSING_ERROR_MSG);
+ if (bodyList.getLength() > 1) log.warn(MULTIPLE_MSG, "<soap11:Body>");
+
+ var body = bodyList.item(0);
+ var children = body.getChildNodes();
+ var candidates = filterNodeByType(children, Node.ELEMENT_NODE);
+
+ if (candidates.isEmpty()) throw moaZSException(SOAP_BODY_CHILDREN_MISSING_ERROR_MSG);
+ if (candidates.size() > 1) log.warn(MULTIPLE_MSG, "<soap11:Body> child");
- return DOMUtils.serializeNode(item, true)
- .getBytes(StandardCharsets.UTF_8);
+ return candidates.get(0);
+ }
- } catch (IOException | TransformerException e) {
- throw MoaZSException.moaZSException("Error while parsing message. ", e);
+ private List<Node> filterNodeByType(NodeList children, short nodeType) {
+ var candidates = new LinkedList<Node>();
+ for (int i = 0; i < children.getLength(); i++) {
+ var child = children.item(i);
+ if (child.getNodeType() == nodeType) {
+ candidates.add(child);
+ }
}
+
+ return candidates;
+ }
+
+ public byte[] toBytes(Node node) throws TransformerException, IOException {
+ return DOMUtils.serializeNode(node, true).getBytes(StandardCharsets.UTF_8);
}
public String getAppDeliveryIDFrom(Element document) {
- var elements = document.getElementsByTagNameNS(NameSpace.MSG, NameSpace.MSG_APP_DELIVERY_ID);
+ var elementList = document.getElementsByTagNameNS(NameSpace.MSG, NameSpace.MSG_APP_DELIVERY_ID);
+
+ if (elementList.getLength() == 0) throw moaZSException(APP_DELIVERY_ID_MISSING_ERROR_MSG);
+ if (elementList.getLength() > 1) log.warn(MULTIPLE_MSG, APP_DELIVERY_ID_FULL_TAG_NAME);
- var appDeliveryIdElement = elements.item(0).getFirstChild();
+ var children = elementList.item(0).getChildNodes();
+ var candidates = filterNodeByType(children, Node.TEXT_NODE);
+ if (candidates.isEmpty() || candidates.get(0).getNodeValue().isBlank())
+ throw moaZSException(APP_DELIVERY_ID_EMPTY_ERROR_MSG);
+ if (candidates.size() > 1) log.warn(MULTIPLE_MSG, APP_DELIVERY_ID_FULL_TAG_NAME);
- return appDeliveryIdElement.getNodeValue();
+ return candidates.get(0).getNodeValue();
}
}
diff --git a/src/main/java/at/gv/egiz/moazs/util/EndpointFactory.java b/src/main/java/at/gv/egiz/moazs/util/EndpointFactory.java
index 24321e1..9d31596 100644
--- a/src/main/java/at/gv/egiz/moazs/util/EndpointFactory.java
+++ b/src/main/java/at/gv/egiz/moazs/util/EndpointFactory.java
@@ -20,13 +20,13 @@ public class EndpointFactory {
this.bus = bus;
}
- public Endpoint create(Object implementor, Service service) {
- return create(implementor, service, null);
+ public Endpoint create(Object implementor, Service service, String route) {
+ return create(implementor, service, route, null);
}
- public Endpoint create(Object implementor, Service service, Interceptor<Message> interceptor) {
+ public Endpoint create(Object implementor, Service service, String route, Interceptor<Message> interceptor) {
EndpointImpl endpoint = new EndpointImpl(bus, implementor);
- endpoint.setAddress("/");
+ endpoint.setAddress(route);
endpoint.setServiceName(service.getServiceName());
endpoint.setWsdlLocation(service.getWSDLDocumentLocation().toString());
endpoint.publish();
diff --git a/src/main/java/at/gv/egiz/moazs/util/StoreSOAPBodyBinaryInRepositoryInterceptor.java b/src/main/java/at/gv/egiz/moazs/util/StoreSOAPBodyBinaryInRepositoryInterceptor.java
index 88ab7e0..d4aa75a 100644
--- a/src/main/java/at/gv/egiz/moazs/util/StoreSOAPBodyBinaryInRepositoryInterceptor.java
+++ b/src/main/java/at/gv/egiz/moazs/util/StoreSOAPBodyBinaryInRepositoryInterceptor.java
@@ -13,6 +13,7 @@ import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
@@ -46,25 +47,22 @@ public class StoreSOAPBodyBinaryInRepositoryInterceptor extends AbstractPhaseInt
try {
byte[] content = messageUtils.copyContent(message);
- if(log.isTraceEnabled()) {
- log.trace("Interceptor received this SOAP message: {}. ", new String(content, StandardCharsets.UTF_8));
- }
-
if (content.length <= 0) {
return;
}
Element document = soapUtils.toDOM(content);
- byte[] response = soapUtils.unwrapSoapEnvelope(document);
- String appDeliveryID = soapUtils.getAppDeliveryIDFrom(document);
- String rootTag = document.getTagName();
+ var rootTagNode = soapUtils.getChildElementOfSoapBody(document);
+ var rootTagLocalName = rootTagNode.getLocalName();
- if (!idGenerators.containsKey(rootTag)) {
- log.trace("Will not store message of type {}. ", rootTag);
+ if (!idGenerators.containsKey(rootTagLocalName)) {
+ log.trace("Child element {} of <soap:Body> is unknown. Will not store message.", rootTagLocalName);
return;
}
- var id = idGenerators.get(rootTag).apply(appDeliveryID);
+ String appDeliveryID = soapUtils.getAppDeliveryIDFrom(document);
+ var id = idGenerators.get(rootTagLocalName).apply(appDeliveryID);
+ byte[] response = soapUtils.toBytes(rootTagNode);
repository.store(id, response);
if(log.isTraceEnabled()) {
@@ -72,7 +70,7 @@ public class StoreSOAPBodyBinaryInRepositoryInterceptor extends AbstractPhaseInt
appDeliveryID, new String(response, StandardCharsets.UTF_8));
}
- } catch (ParserConfigurationException | SAXException | IOException | NullPointerException e) {
+ } catch (ParserConfigurationException | SAXException | IOException | NullPointerException | TransformerException e) {
throw moaZSException("Could not extract signed data from message.", e);
}
}