View Javadoc
1   /*
2    * Copyright 2016 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.openehealth.ipf.platform.camel.ihe.fhir.core.intercept.producer;
17  
18  import org.apache.camel.Exchange;
19  import org.hl7.fhir.instance.model.api.IBaseResource;
20  import org.openehealth.ipf.commons.audit.AuditContext;
21  import org.openehealth.ipf.commons.audit.codes.EventOutcomeIndicator;
22  import org.openehealth.ipf.commons.ihe.core.atna.AuditStrategy;
23  import org.openehealth.ipf.commons.ihe.fhir.audit.FhirAuditDataset;
24  import org.openehealth.ipf.platform.camel.ihe.atna.interceptor.AuditInterceptor;
25  import org.openehealth.ipf.platform.camel.ihe.core.InterceptorSupport;
26  import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirComponent;
27  import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpoint;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  import static java.util.Objects.requireNonNull;
32  import static org.openehealth.ipf.platform.camel.core.util.Exchanges.resultMessage;
33  
34  
35  /**
36   * Consumer-side FHIR ATNA auditing Camel interceptor.
37   *
38   * @author Christian Ohr
39   * @since 3.1
40   */
41  public class ProducerAuditInterceptor<AuditDatasetType extends FhirAuditDataset>
42          extends InterceptorSupport<FhirEndpoint<AuditDatasetType, FhirComponent<AuditDatasetType>>>
43          implements AuditInterceptor<AuditDatasetType, FhirEndpoint<AuditDatasetType, FhirComponent<AuditDatasetType>>> {
44  
45      private static final Logger LOG = LoggerFactory.getLogger(ProducerAuditInterceptor.class);
46  
47      private final AuditContext auditContext;
48  
49      public ProducerAuditInterceptor(AuditContext auditContext) {
50          this.auditContext = requireNonNull(auditContext);
51      }
52  
53      @Override
54      public void process(Exchange exchange) throws Exception {
55          IBaseResource msg = exchange.getIn().getBody(IBaseResource.class);
56  
57          AuditDatasetType auditDataset = createAndEnrichAuditDatasetFromRequest(getAuditStrategy(), exchange, msg);
58          determineParticipantsAddresses(exchange, auditDataset);
59  
60          boolean failed = false;
61          try {
62              getWrappedProcessor().process(exchange);
63              IBaseResource result = resultMessage(exchange).getBody(IBaseResource.class);
64              failed = !enrichAuditDatasetFromResponse(getAuditStrategy(), auditDataset, result);
65          } catch (Exception e) {
66              // FHIR exception or unexpected exception
67              failed = true;
68              throw e;
69          } finally {
70              if (auditDataset != null) {
71                  auditDataset.setEventOutcomeIndicator(failed ?
72                          EventOutcomeIndicator.MajorFailure :
73                          EventOutcomeIndicator.Success);
74                  getAuditStrategy().doAudit(auditContext, auditDataset);
75              }
76          }
77      }
78  
79      @Override
80      public void determineParticipantsAddresses(Exchange exchange, AuditDatasetType auditDataset) {
81      }
82  
83      @Override
84      public AuditStrategy<AuditDatasetType> getAuditStrategy() {
85          return getEndpoint().getClientAuditStrategy();
86      }
87  
88      /**
89       * Creates a new audit dataset and enriches it with data from the request
90       * message.  All exception are ignored.
91       *
92       * @return newly created audit dataset or <code>null</code> when creation failed.
93       */
94      private AuditDatasetType createAndEnrichAuditDatasetFromRequest(AuditStrategy<AuditDatasetType> strategy, Exchange exchange, IBaseResource msg) {
95          try {
96              AuditDatasetType auditDataset = strategy.createAuditDataset();
97              auditDataset.setSourceUserId("unknown");
98              auditDataset.setDestinationUserId(exchange.getProperty("CamelToEndpoint").toString());
99  
100             // TODO set client-side headers
101             return strategy.enrichAuditDatasetFromRequest(auditDataset, msg, exchange.getIn().getHeaders());
102         } catch (Exception e) {
103             LOG.error("Exception when enriching audit dataset from request", e);
104             return null;
105         }
106     }
107 
108 
109     /**
110      * Enriches the given audit dataset with data from the response message.
111      * All exception are ignored.
112      */
113     private boolean enrichAuditDatasetFromResponse(AuditStrategy<AuditDatasetType> strategy, AuditDatasetType auditDataset, IBaseResource response) {
114         return strategy.enrichAuditDatasetFromResponse(auditDataset, response, auditContext);
115     }
116 
117 
118 }