View Javadoc
1   /*
2    * Copyright 2015 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  
17  package org.openehealth.ipf.platform.camel.ihe.core;
18  
19  import org.apache.camel.Consumer;
20  import org.apache.camel.Endpoint;
21  import org.apache.camel.Processor;
22  import org.apache.camel.Producer;
23  import org.openehealth.ipf.commons.ihe.core.chain.ChainUtils;
24  
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.function.Function;
28  
29  /**
30   * Interface for endpoints that use the Interceptor framework defined in this module.
31   *
32   * This has been changed to an interface with default methods as of IPF 3.2 so that it
33   * can also be used when extending other endpoint types than DefaultEndpoint.
34   *
35   * @since 3.1
36   */
37  public interface InterceptableEndpoint<
38          ConfigType extends InterceptableEndpointConfiguration,
39          ComponentType extends InterceptableComponent> extends Endpoint {
40  
41  
42      /**
43       * Default implementation that creates a producer by calling {@link #doCreateProducer()}
44       * and weaves in configured interceptor processors to be executed before reaching out
45       * for the target
46       *
47       * @return intercepted producer
48       * @throws Exception
49       */
50      @Override
51      default Producer createProducer() throws Exception {
52          Producer producer = doCreateProducer();
53  
54          List<Interceptor> initialChain = createInitialProducerInterceptorChain();
55          List<Interceptor> additionalInterceptors = new ArrayList<>();
56          additionalInterceptors.addAll(getInterceptableComponent().getAdditionalProducerInterceptors());
57          // add interceptors provided by the user
58          additionalInterceptors.addAll(getCustomInterceptors());
59          List<Interceptor> producerInterceptorChain = ChainUtils.createChain(initialChain, additionalInterceptors);
60  
61          return InterceptorUtils.adaptProducerChain(
62                  producerInterceptorChain,
63                  this,
64                  producer);
65      }
66  
67      /**
68       * Default implementation that creates a consumer by calling {@link #doCreateConsumer(Processor)}
69       * and weaves in configured interceptor processors to be executed before calling the first
70       * processor in the consumer route.
71       *
72       * @param originalProcessor processor for handling the consumed request
73       * @return intercepted consumer
74       * @throws Exception
75       */
76      @Override
77      default Consumer createConsumer(Processor originalProcessor) throws Exception {
78          // Configure interceptor chain
79          List<Interceptor> initialChain = createInitialConsumerInterceptorChain();
80  
81          List<Interceptor> additionalInterceptors = new ArrayList<>();
82          additionalInterceptors.addAll(getInterceptableComponent().getAdditionalConsumerInterceptors());
83          // add interceptors provided by the user
84          additionalInterceptors.addAll(getCustomInterceptors());
85          List<Interceptor> consumerInterceptorChain = ChainUtils.createChain(initialChain, additionalInterceptors);
86  
87          Processor processor = originalProcessor;
88          for (int i = consumerInterceptorChain.size() - 1; i >= 0; --i) {
89              Interceptor interceptor = consumerInterceptorChain.get(i);
90              interceptor.setWrappedProcessor(processor);
91              interceptor.setEndpoint(this);
92              processor = interceptor;
93          }
94          // Create the component-specific consumer
95          return doCreateConsumer(processor);
96      }
97  
98      /**
99       * Returns a list of endpoint-specific custom interceptors from {@link #getInterceptableConfiguration()}
100      *
101      * @return a list of endpoint-specific custom interceptors
102      */
103     default List<Interceptor> getCustomInterceptors() {
104         List<Interceptor> result = new ArrayList<>();
105         List<InterceptorFactory> factories = getInterceptableConfiguration().getCustomInterceptorFactories();
106         factories.stream()
107                 .map((Function<InterceptorFactory, Interceptor>) InterceptorFactory::getNewInstance)
108                 .forEach(result::add);
109         return result;
110     }
111 
112     /**
113      * @return the actual producer without any interceptors configured
114      * @throws Exception
115      */
116     Producer doCreateProducer() throws Exception;
117 
118     /**
119      * @return the actual consumer without any interceptors configured
120      * @throws Exception
121      */
122     Consumer doCreateConsumer(Processor processor) throws Exception;
123 
124     /**
125      * @return the component for this endpoint
126      */
127     ComponentType getInterceptableComponent();
128 
129     /**
130      * @return the configuration for this endpoint
131      */
132     ConfigType getInterceptableConfiguration();
133 
134     /**
135      * @return the initial chain of consumer interceptors for this endpoint
136      */
137     List<Interceptor> createInitialConsumerInterceptorChain();
138 
139     /**
140      * @return the initial chain of producer interceptors for this endpoint
141      */
142     List<Interceptor> createInitialProducerInterceptorChain();
143 }