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.consumer;
17  
18  import org.apache.camel.Exchange;
19  import org.openehealth.ipf.commons.audit.AuditContext;
20  import org.openehealth.ipf.commons.audit.codes.EventOutcomeIndicator;
21  import org.openehealth.ipf.commons.ihe.core.atna.AuditStrategy;
22  import org.openehealth.ipf.commons.ihe.fhir.Constants;
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 ConsumerAuditInterceptor<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(ConsumerAuditInterceptor.class);
46  
47      private final AuditContext auditContext;
48  
49      public ConsumerAuditInterceptor(AuditContext auditContext) {
50          this.auditContext = requireNonNull(auditContext);
51      }
52  
53      @Override
54      public void process(Exchange exchange) throws Exception {
55          AuditDatasetType auditDataset = createAndEnrichAuditDatasetFromRequest(getAuditStrategy(), exchange, exchange.getIn().getBody());
56          determineParticipantsAddresses(exchange, auditDataset);
57  
58          boolean failed = false;
59          try {
60              getWrappedProcessor().process(exchange);
61              failed = exchange.isFailed();
62              if (!failed) {
63                  Object result = resultMessage(exchange).getBody();
64                  failed = !getAuditStrategy().enrichAuditDatasetFromResponse(auditDataset, result, auditContext);
65              }
66          } catch (Exception e) {
67              // In case of an exception thrown from the route, the FHIRServlet will generate an
68              // appropriate error response
69              if (auditDataset != null) {
70                  auditDataset.setEventOutcomeDescription(e.getMessage());
71              }
72              failed = true;
73              throw e;
74          } finally {
75              if (auditDataset != null) {
76                  auditDataset.setEventOutcomeIndicator(failed ?
77                          EventOutcomeIndicator.MajorFailure :
78                          EventOutcomeIndicator.Success);
79                  getAuditStrategy().doAudit(auditContext, auditDataset);
80              }
81          }
82      }
83  
84      @Override
85      public void determineParticipantsAddresses(Exchange exchange, AuditDatasetType auditDataset) {
86      }
87  
88      @Override
89      public AuditStrategy<AuditDatasetType> getAuditStrategy() {
90          return getEndpoint().getServerAuditStrategy();
91      }
92  
93      /**
94       * Creates a new audit dataset and enriches it with data from the request
95       * message.  All exception are ignored.
96       *
97       * @return newly created audit dataset or <code>null</code> when creation failed.
98       */
99      private AuditDatasetType createAndEnrichAuditDatasetFromRequest(AuditStrategy<AuditDatasetType> strategy, Exchange exchange, Object msg) {
100         try {
101             AuditDatasetType auditDataset = strategy.createAuditDataset();
102             auditDataset.setSourceUserId("unknown");
103             auditDataset.setDestinationUserId(exchange.getIn().getHeader(Constants.HTTP_URL, String.class));
104 
105             // TODO Also extract basic auth user?
106             AuditInterceptorUtils.extractClientCertificateCommonName(exchange, auditDataset);
107 
108             return strategy.enrichAuditDatasetFromRequest(auditDataset, msg, exchange.getIn().getHeaders());
109         } catch (Exception e) {
110             LOG.error("Exception when enriching audit dataset from request", e);
111             return null;
112         }
113     }
114 
115 
116 
117 }