aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/gv/egiz/moazs/scheme
diff options
context:
space:
mode:
authorChristof Rabensteiner <christof.rabensteiner@iaik.tugraz.at>2019-07-03 15:27:14 +0200
committerChristof Rabensteiner <christof.rabensteiner@iaik.tugraz.at>2019-07-03 15:27:14 +0200
commit78f0715d86a055aed11138df5f66b0794e72326a (patch)
tree4f5e16fea5740e25ee22e98e8940fa28365a2a93 /src/main/java/at/gv/egiz/moazs/scheme
parent8bcd9c265198e8d46e2ec862ca6e0cb47838bd7f (diff)
downloadmoa-zs-78f0715d86a055aed11138df5f66b0794e72326a.tar.gz
moa-zs-78f0715d86a055aed11138df5f66b0794e72326a.tar.bz2
moa-zs-78f0715d86a055aed11138df5f66b0794e72326a.zip
Refactor: Restructure Project
- Move components that depend on the service contracts into scheme package. - Move cxf related components into util package. - Rename SameThread to SingleThreaded.
Diffstat (limited to 'src/main/java/at/gv/egiz/moazs/scheme')
-rw-r--r--src/main/java/at/gv/egiz/moazs/scheme/MzsClient.java13
-rw-r--r--src/main/java/at/gv/egiz/moazs/scheme/MzsDeliveryRequestValidator.java74
-rw-r--r--src/main/java/at/gv/egiz/moazs/scheme/MzsService.java104
-rw-r--r--src/main/java/at/gv/egiz/moazs/scheme/TnvzHelper.java232
4 files changed, 423 insertions, 0 deletions
diff --git a/src/main/java/at/gv/egiz/moazs/scheme/MzsClient.java b/src/main/java/at/gv/egiz/moazs/scheme/MzsClient.java
new file mode 100644
index 0000000..98e0bc8
--- /dev/null
+++ b/src/main/java/at/gv/egiz/moazs/scheme/MzsClient.java
@@ -0,0 +1,13 @@
+package at.gv.egiz.moazs.scheme;
+
+import at.gv.zustellung.app2mzs.xsd.DeliveryResponseType;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MzsClient {
+
+ public void sendNotification(DeliveryResponseType responseType) {
+ throw new UnsupportedOperationException("Not implemented.");
+ }
+
+}
diff --git a/src/main/java/at/gv/egiz/moazs/scheme/MzsDeliveryRequestValidator.java b/src/main/java/at/gv/egiz/moazs/scheme/MzsDeliveryRequestValidator.java
new file mode 100644
index 0000000..03f2664
--- /dev/null
+++ b/src/main/java/at/gv/egiz/moazs/scheme/MzsDeliveryRequestValidator.java
@@ -0,0 +1,74 @@
+package at.gv.egiz.moazs.scheme;
+
+import at.gv.zustellung.app2mzs.xsd.ClientType;
+import at.gv.zustellung.app2mzs.xsd.ConfigType;
+import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType;
+import at.gv.zustellung.app2mzs.xsd.KeyStoreType;
+import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Component;
+
+@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.
+ */
+ public boolean isTnvzComplete(DeliveryRequestType request) {
+ return !request.getConfig().isPerformQueryPersonRequest() ||
+ (request.getTnvzMetaData() != null
+ && request.getSender().getCorporateBody() != null);
+
+
+ }
+
+ /**
+ * Check if all mandatory fields of configuration are present.
+ *
+ * @param profile
+ * @return true if all mandatory fields are present.
+ */
+ public boolean isConfigProfileComplete(@Nullable ConfigType profile) {
+ return profile != null
+ && profile.isPerformQueryPersonRequest() != null
+ && isTVNZClientConfigured(profile.getTNVZClient(), profile.isPerformQueryPersonRequest())
+ && isMSGClientConfigured(profile.getMSGClient());
+ }
+
+ private boolean isTVNZClientConfigured(ClientType tnvzClient, Boolean isPerformQueryPersonRequest) {
+ return !isPerformQueryPersonRequest || (tnvzClient != null
+ && tnvzClient.getURL() != null
+ && tnvzClient.getReceiveTimeout() != null
+ && tnvzClient.getConnectionTimeout() != null
+ && isSSLConfigured(tnvzClient));
+ }
+
+ private boolean isMSGClientConfigured(ClientType msgClientParams) {
+ return msgClientParams != null
+ && msgClientParams.getURL() != null
+ && isSSLConfigured(msgClientParams)
+ && msgClientParams.getReceiveTimeout() != null
+ && msgClientParams.getConnectionTimeout() != null;
+ }
+
+ 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 boolean isKeyStoreConfigured(KeyStoreType keyStore) {
+ return keyStore == null || (keyStore.getPassword() != null
+ && keyStore.getFileType() != null
+ && keyStore.getFileName() != null);
+ }
+
+ private boolean isTrustStoreConfigured(KeyStoreType trustStore) {
+ return trustStore == null || (trustStore.getPassword() != null
+ && "JKS".equals(trustStore.getFileType())
+ && trustStore.getFileName() != null);
+ }
+}
diff --git a/src/main/java/at/gv/egiz/moazs/scheme/MzsService.java b/src/main/java/at/gv/egiz/moazs/scheme/MzsService.java
new file mode 100644
index 0000000..f245b93
--- /dev/null
+++ b/src/main/java/at/gv/egiz/moazs/scheme/MzsService.java
@@ -0,0 +1,104 @@
+package at.gv.egiz.moazs.scheme;
+
+import at.gv.egiz.moazs.pipeline.DeliveryPipeline;
+import at.gv.egiz.moazs.preprocess.DeliveryRequestAugmenter;
+import at.gv.egiz.moazs.repository.DeliveryRepository;
+import at.gv.zustellung.app2mzs.xsd.App2MzsPortType;
+import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType;
+import at.gv.zustellung.app2mzs.xsd.DeliveryResponseType;
+import at.gv.zustellung.msg.xsd.DeliveryRequestStatusType;
+import org.apache.cxf.annotations.SchemaValidation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.jws.WebParam;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import static at.gv.egiz.moazs.MoaZSException.moaZSException;
+import static at.gv.egiz.moazs.MoaZSException.moaZSExceptionBuilder;
+import static at.gv.zustellung.app2mzs.xsd.PartialSuccessType.partialSuccessTypeBuilder;
+import static java.util.concurrent.CompletableFuture.supplyAsync;
+
+//todo : validate Schema in both directions.
+@Service
+@SchemaValidation(type = SchemaValidation.SchemaValidationType.IN)
+public class MzsService implements App2MzsPortType {
+
+ private static final Logger logger = LoggerFactory.getLogger(MzsService.class);
+
+ //TODO move timeout and namespaces to config
+ private static final int TIMEOUT_FOR_ANWSER = 10;
+
+ private final DeliveryRepository repository;
+ private final DeliveryPipeline pipeline;
+ private final MzsClient appClient;
+ private final DeliveryRequestAugmenter augmenter;
+ private final Msg2MzsConverter converter;
+
+ @Autowired
+ public MzsService(DeliveryRepository repository, DeliveryPipeline pipeline, MzsClient appClient,
+ DeliveryRequestAugmenter augmenter, Msg2MzsConverter converter) {
+ this.repository = repository;
+ this.pipeline = pipeline;
+ this.appClient = appClient;
+ this.augmenter = augmenter;
+ this.converter = converter;
+ }
+
+ @Override
+ public DeliveryResponseType app2Mzs(
+ @WebParam(partName = "DeliveryRequest",
+ name = "DeliveryRequest")
+ DeliveryRequestType deliveryRequest) {
+
+ var appDeliveryID = deliveryRequest.getMetaData().getAppDeliveryID();
+
+ var future = supplyAsync(() -> augmenter.augment(deliveryRequest))
+ .thenApply(this::process)
+ .thenApply(status -> converter.convert(status, repository.getSignedDeliveryRequestStatus(appDeliveryID)));
+
+ try {
+ return future.get(TIMEOUT_FOR_ANWSER, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ logger.info("Answer Timed Out", e);
+
+ future.thenAccept(appClient::sendNotification);
+ return generatePartialSuccessResponse(appDeliveryID);
+
+ } catch (Exception e) {
+ throw moaZSExceptionBuilder("An error occurred while processing DeliveryRequest " +
+ "with AppDeliveryID=%s.", appDeliveryID)
+ .withCause(e)
+ .build();
+ }
+
+ }
+
+ private DeliveryRequestStatusType process(DeliveryRequestType deliveryRequest) {
+
+ var appDeliveryID = deliveryRequest.getMetaData().getAppDeliveryID();
+ logger.info("Receive request with appDeliveryID = {}.", appDeliveryID);
+
+ repository.add(deliveryRequest);
+ pipeline.processRequest(appDeliveryID);
+
+ return repository.getDeliveryRequestStatus(appDeliveryID)
+ .orElseThrow(() -> moaZSException("Could not get a response for AppDeliveryID=%s.", appDeliveryID));
+
+ }
+
+ private DeliveryResponseType generatePartialSuccessResponse(String appDeliveryId) {
+
+ var partial = partialSuccessTypeBuilder()
+ .withAppDeliveryID(appDeliveryId)
+ .build();
+
+ return DeliveryResponseType.deliveryResponseTypeBuilder()
+ .withPartialSuccess(partial)
+ .build();
+ }
+
+}
diff --git a/src/main/java/at/gv/egiz/moazs/scheme/TnvzHelper.java b/src/main/java/at/gv/egiz/moazs/scheme/TnvzHelper.java
new file mode 100644
index 0000000..70c20bb
--- /dev/null
+++ b/src/main/java/at/gv/egiz/moazs/scheme/TnvzHelper.java
@@ -0,0 +1,232 @@
+package at.gv.egiz.moazs.scheme;
+
+import at.gv.egiz.moazs.MoaZSException;
+import at.gv.egiz.moazs.scheme.Mzs2MsgConverter;
+import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType;
+import at.gv.zustellung.app2mzs.xsd.persondata.AbstractAddressType;
+import at.gv.zustellung.msg.xsd.persondata.IdentificationType;
+import at.gv.zustellung.msg.xsd.persondata.ObjectFactory;
+import at.gv.zustellung.msg.xsd.persondata.PostalAddressType;
+import at.gv.zustellung.tnvz.xsd.*;
+import at.gv.zustellung.tnvz.xsd.QueryPersonRequest.QueryEntryList;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Nullable;
+import javax.xml.bind.JAXBElement;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static at.gv.zustellung.tnvz.xsd.PersonQueryType.MetaData.metaDataBuilder;
+import static at.gv.zustellung.tnvz.xsd.PersonQueryType.personQueryTypeBuilder;
+import static at.gv.zustellung.tnvz.xsd.QueryPersonRequest.QueryEntryList.queryEntryListBuilder;
+import static at.gv.zustellung.tnvz.xsd.QueryPersonRequest.queryPersonRequestBuilder;
+import static at.gv.zustellung.tnvz.xsd.Receiver.receiverBuilder;
+import static at.gv.zustellung.tnvz.xsd.Sender.senderBuilder;
+import static java.lang.String.join;
+import static java.util.stream.Collectors.toSet;
+
+@Component
+public class TnvzHelper {
+
+ private final Mzs2MsgConverter converter;
+
+ private static final ObjectFactory FACTORY = new at.gv.zustellung.msg.xsd.persondata.ObjectFactory();
+ private static final String ENTRY_ID = "entry-id";
+ private static final String RECEIVER_NOT_ADRESSABLE_ERROR_MSG = "Receiver is not addressable. Reason: %s";
+ private static final String MIMETYPE_MISSMATCH_ERROR_MSG = "Request contains attachment of type(s) %s, but " +
+ "receiver only accepts attachments of type(s) %s.";
+ private static final String MZS_NO_TNVZ_PERSON_QUERY_RESULTS_ERROR_MSG = "tnvz:QueryResultList was empty.";
+
+
+ @Autowired
+ public TnvzHelper(Mzs2MsgConverter converter) {
+ this.converter = converter;
+ }
+
+ /**
+ * Performs all tasks related to making a request to the tnvz service:
+ * Derives a tnvz:QueryPersonRequest from the {@code mzsRequest}, sends the QueryPersonRequest to
+ * {@code tvnzPort}, validates the tnvz's response and extracts the {@code Identification} Element.
+ * @param mzsRequest Data source for the QueryPersonRequest
+ * @param tvnzPort Client for communicating with the tnvz service
+ * @param exceptionBuilder Utility to collect information and build a meaningful exception in case of errors.
+ * @throws MoaZSException in case of an error.
+ * @return
+ */
+ public IdentificationType performQueryPersonRequest(DeliveryRequestType mzsRequest,
+ TNVZServicePort tvnzPort,
+ MoaZSException.Builder exceptionBuilder) {
+
+ var tvnzQuery = buildQuery(mzsRequest);
+ var tvnzResponse = tvnzPort.queryPerson(tvnzQuery);
+ verifyResponse(tvnzResponse, exceptionBuilder);
+
+ var tvnzResult = getResult(tvnzResponse);
+ var typesInRequest = extractListOfMimemtypesIn(mzsRequest);
+ checkMimetypes(tvnzResult, typesInRequest, exceptionBuilder);
+
+ return tvnzResult.getSuccess().getIdentification();
+ }
+
+ private QueryPersonRequest buildQuery(DeliveryRequestType mzsRequest) {
+
+ Sender sender = extractSender(mzsRequest.getSender());
+ Receiver receiver = extractReceiver(mzsRequest.getReceiver());
+ var metadata = extractMetaData(mzsRequest);
+
+ PersonQueryType personQuery = personQueryTypeBuilder()
+ .withEntryID(ENTRY_ID)
+ .withSender(sender)
+ .withReceiver(receiver)
+ .withMetaData(metadata)
+ .build();
+
+ QueryEntryList entryList = queryEntryListBuilder()
+ .withQueryEntry(List.of(personQuery))
+ .build();
+
+ return queryPersonRequestBuilder()
+ .withQueryEntryList(entryList)
+ .build();
+ }
+
+ private PersonQueryType.MetaData extractMetaData(DeliveryRequestType request) {
+
+ var builder = metaDataBuilder();
+
+ var meta = request.getTnvzMetaData();
+
+ if (meta.getDeliveryQuality() != null) {
+ builder.withDeliveryQuality(meta.getDeliveryQuality());
+ } else {
+ builder.withPrivateMessageQuality(meta.getPrivateMessageQuality());
+ }
+
+ return builder
+ .withOrigin(meta.getOrigin())
+ .withPreAdviceNote(request.getReceiver().getPreAdviceNote())
+ .withIgnorePostRedirectionOrder(meta.getIgnorePostRedirectionOrder())
+ .build();
+ }
+
+ private Sender extractSender(DeliveryRequestType.Sender sender) {
+
+ var corporateBody = sender.getCorporateBody();
+ var mzsIdentification = corporateBody.getIdentification().get(0);
+ var msgIdentification = converter.convert(mzsIdentification);
+
+ var msgPerson = FACTORY.createPerson(converter.convert(corporateBody));
+
+ return senderBuilder()
+ .withIdentification(msgIdentification)
+ .withPerson(msgPerson)
+ .build();
+ }
+
+ private Receiver extractReceiver(DeliveryRequestType.Receiver receiver) {
+
+ var builder = receiverBuilder();
+
+ if (receiver.getIdentification() == null) {
+ builder
+ .withPerson(converter.convert(receiver.getPerson()))
+ .withAustrianAddressesOnly(receiver.getAustrianAddressesOnly());
+
+ var postalAddress = findPostalAddress(receiver.getAddress());
+ if (postalAddress != null)
+ builder.withPostalAddress(postalAddress);
+
+ if (receiver.getPreAdviceNote() != null) {
+ builder.withNotificationAddressList(receiver.getPreAdviceNote().getNotificationAddressList());
+ }
+ } else {
+ builder.withIdentification(converter.convert(receiver.getIdentification()));
+ }
+
+ return builder.build();
+ }
+
+ private @Nullable PostalAddressType findPostalAddress(List<JAXBElement<? extends AbstractAddressType>> addresses) {
+
+ if (addresses == null) return null;
+
+ for (JAXBElement<? extends AbstractAddressType> address : addresses) {
+ if(address.getValue() instanceof at.gv.zustellung.app2mzs.xsd.persondata.PostalAddressType) {
+ var mzsPostalAddress = (at.gv.zustellung.app2mzs.xsd.persondata.PostalAddressType) address.getValue();
+ return converter.convert(mzsPostalAddress);
+ }
+ }
+
+ return null;
+
+ }
+
+ private Set<String> extractListOfMimemtypesIn(DeliveryRequestType mzsRequest) {
+ return mzsRequest.getPayload().stream()
+ .map(DeliveryRequestType.Payload::getMIMEType)
+ .collect(toSet());
+ }
+
+ private void verifyResponse(QueryPersonResponse tvnzResponse, MoaZSException.Builder mzsBuilder) {
+
+ var error = tvnzResponse.getError();
+ if (error != null) {
+ throw mzsBuilder.withErrorCode(error.getCode())
+ .withMessage(error.getText())
+ .build();
+ }
+
+ var results = tvnzResponse.getQueryResultList().getQueryResult();
+ if (results.isEmpty()) {
+ throw mzsBuilder.withErrorCode(MoaZSException.ERROR_MZS_NO_TNVZ_PERSON_QUERY_RESULTS)
+ .withMessage(MZS_NO_TNVZ_PERSON_QUERY_RESULTS_ERROR_MSG)
+ .build();
+ }
+
+ var tnvzResult = results.get(0);
+ mzsBuilder.withTnvzResult(tnvzResult);
+ if (tnvzResult.getError() != null) {
+ var info = tnvzResult.getError().getErrorInfo();
+ throw mzsBuilder.withErrorCode(info.getCode())
+ .withMessage(RECEIVER_NOT_ADRESSABLE_ERROR_MSG, info.getText())
+ .build();
+ }
+ }
+
+ private PersonResultType getResult(QueryPersonResponse tvnzResponse) {
+ return tvnzResponse.getQueryResultList().getQueryResult().get(0);
+ }
+
+ private void checkMimetypes(PersonResultType tnvzResult, Set<String> typesInRequest, MoaZSException.Builder mzsBuilder) {
+ var mismatchedTypes = findMimeTypeMismatches(tnvzResult, typesInRequest);
+ if (!mismatchedTypes.isEmpty()) {
+ var acceptedTypesString = join(",", getAcceptedTypes(tnvzResult));
+ var mismatchedTypesString = join(",", mismatchedTypes);
+ throw mzsBuilder.withErrorCode(MoaZSException.ERROR_MZS_MIMETYPE_MISSMATCH)
+ .withMessage(MIMETYPE_MISSMATCH_ERROR_MSG, mismatchedTypesString, acceptedTypesString)
+ .build();
+ }
+ }
+
+ private Collection<String> findMimeTypeMismatches(PersonResultType result, Set<String> typesInRequest) {
+ var acceptedTypes = getAcceptedTypes(result);
+
+ if (acceptedTypes.contains("*/*")) {
+ return List.of();
+ }
+
+ var typesInRequestCopy = new HashSet<>(typesInRequest);
+ typesInRequestCopy.removeAll(acceptedTypes);
+
+ return typesInRequestCopy;
+ }
+
+ private List<String> getAcceptedTypes(PersonResultType result) {
+ return result.getSuccess().getMimeTypeList().getMimeType();
+ }
+
+
+}