1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.openehealth.ipf.platform.camel.ihe.mllp.core;
17
18 import lombok.AccessLevel;
19 import lombok.Getter;
20 import org.apache.camel.*;
21 import org.apache.camel.api.management.ManagedAttribute;
22 import org.apache.camel.api.management.ManagedResource;
23 import org.apache.camel.component.mina2.Mina2Configuration;
24 import org.apache.camel.component.mina2.Mina2Consumer;
25 import org.apache.camel.component.mina2.Mina2Endpoint;
26 import org.apache.camel.component.mina2.Mina2Producer;
27 import org.apache.camel.impl.DefaultEndpoint;
28 import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
29 import org.apache.mina.core.filterchain.IoFilter;
30 import org.apache.mina.core.session.IoSession;
31 import org.openehealth.ipf.commons.audit.model.AuditMessage;
32 import org.openehealth.ipf.commons.ihe.core.ClientAuthType;
33 import org.openehealth.ipf.commons.ihe.hl7v2.Hl7v2InteractionId;
34 import org.openehealth.ipf.commons.ihe.hl7v2.Hl7v2TransactionConfiguration;
35 import org.openehealth.ipf.commons.ihe.hl7v2.NakFactory;
36 import org.openehealth.ipf.commons.ihe.hl7v2.audit.MllpAuditDataset;
37 import org.openehealth.ipf.commons.ihe.hl7v2.audit.MllpAuditUtils;
38 import org.openehealth.ipf.platform.camel.ihe.core.InterceptableEndpoint;
39 import org.openehealth.ipf.platform.camel.ihe.core.InterceptorFactory;
40 import org.openehealth.ipf.platform.camel.ihe.hl7v2.HL7v2Endpoint;
41 import org.openehealth.ipf.platform.camel.ihe.mllp.core.intercept.consumer.ConsumerDispatchingInterceptor;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 import javax.net.ssl.SSLContext;
46 import java.util.List;
47 import java.util.Map;
48
49 import static java.util.Objects.requireNonNull;
50
51
52
53
54
55
56
57 @ManagedResource(description = "Managed IPF MLLP ITI Endpoint")
58 public abstract class MllpEndpoint<
59 ConfigType extends MllpEndpointConfiguration,
60 AuditDatasetType extends MllpAuditDataset,
61 ComponentType extends MllpComponent<ConfigType, AuditDatasetType>>
62 extends DefaultEndpoint
63 implements InterceptableEndpoint<ConfigType, ComponentType>, HL7v2Endpoint<AuditDatasetType> {
64
65 private static final Logger LOG = LoggerFactory.getLogger(MllpEndpoint.class);
66
67 @Getter(AccessLevel.PROTECTED)
68 private final ConfigType config;
69 @Getter(AccessLevel.PROTECTED)
70 private final ComponentType mllpComponent;
71 @Getter(AccessLevel.PROTECTED)
72 private final Mina2Endpoint wrappedEndpoint;
73
74
75
76
77
78
79
80
81 public MllpEndpoint(
82 ComponentType mllpComponent,
83 Mina2Endpoint wrappedEndpoint,
84 ConfigType config) {
85 super(wrappedEndpoint.getEndpointUri(), mllpComponent);
86 this.mllpComponent = requireNonNull(mllpComponent);
87 this.wrappedEndpoint = requireNonNull(wrappedEndpoint);
88 this.config = requireNonNull(config);
89 }
90
91 @Override
92 public ComponentType getInterceptableComponent() {
93 return mllpComponent;
94 }
95
96 @Override
97 public ConfigType getInterceptableConfiguration() {
98 return config;
99 }
100
101
102
103
104
105 @Override
106 public Producer doCreateProducer() throws Exception {
107 Mina2Producer producer = (Mina2Producer) wrappedEndpoint.createProducer();
108 if (config.getSslContext() != null) {
109 DefaultIoFilterChainBuilder filterChain = producer.getFilterChain();
110 if (!filterChain.contains("ssl")) {
111 HandshakeCallbackSSLFilter filter = new HandshakeCallbackSSLFilter(config.getSslContext());
112 filter.setUseClientMode(true);
113 filter.setHandshakeExceptionCallback(new HandshakeFailureCallback());
114 filter.setEnabledProtocols(config.getSslProtocols());
115 filter.setEnabledCipherSuites(config.getSslCiphers());
116 filterChain.addFirst("ssl", filter);
117 }
118 }
119 return new MllpProducer(producer);
120 }
121
122
123
124
125
126
127
128 @Override
129 public Consumer doCreateConsumer(Processor processor) throws Exception {
130 Mina2Consumer consumer = (Mina2Consumer) wrappedEndpoint.createConsumer(processor);
131 if (config.getSslContext() != null) {
132 DefaultIoFilterChainBuilder filterChain = consumer.getAcceptor().getFilterChain();
133 if (!filterChain.contains("ssl")) {
134 HandshakeCallbackSSLFilter filter = new HandshakeCallbackSSLFilter(config.getSslContext());
135 filter.setNeedClientAuth(config.getClientAuthType() == ClientAuthType.MUST);
136 filter.setWantClientAuth(config.getClientAuthType() == ClientAuthType.WANT);
137 filter.setHandshakeExceptionCallback(new HandshakeFailureCallback());
138 filter.setEnabledProtocols(config.getSslProtocols());
139 filter.setEnabledCipherSuites(config.getSslCiphers());
140 filterChain.addFirst("ssl", filter);
141 }
142 }
143 consumer.getAcceptor().getFilterChain().addLast("mllp.exception.filter", new MllpExceptionIoFilter(consumer));
144 return new MllpConsumer(consumer);
145 }
146
147
148 private class HandshakeFailureCallback implements HandshakeCallbackSSLFilter.Callback {
149
150 @Override
151 public void run(IoSession session, String message) {
152 if (config.isAudit()) {
153 String hostAddress = session.getRemoteAddress().toString();
154 AuditMessage auditMessage = MllpAuditUtils.auditAuthenticationNodeFailure(
155 config.getAuditContext(), message, hostAddress);
156 config.getAuditContext().audit(auditMessage);
157 }
158 }
159 }
160
161
162
163
164
165
166 @Override
167 public Hl7v2TransactionConfiguration<AuditDatasetType> getHl7v2TransactionConfiguration() {
168 return mllpComponent.getHl7v2TransactionConfiguration();
169 }
170
171
172
173
174 @Override
175 public NakFactory<AuditDatasetType> getNakFactory() {
176 return mllpComponent.getNakFactory();
177 }
178
179 @Override
180 public Hl7v2InteractionId<AuditDatasetType> getInteractionId() {
181 return mllpComponent.getInteractionId();
182 }
183
184
185
186
187 @ManagedAttribute(description = "Support Segment Fragmentation Enabled")
188 public boolean isSupportSegmentFragmentation() {
189 return config.isSupportSegmentFragmentation();
190 }
191
192
193
194
195 @ManagedAttribute(description = "Segment Fragmentation Threshold")
196 public int getSegmentFragmentationThreshold() {
197 return config.getSegmentFragmentationThreshold();
198 }
199
200
201
202
203 public SSLContext getSslContext() {
204 return config.getSslContext();
205 }
206
207
208
209
210 @ManagedAttribute(description = "Defined SSL Protocols")
211 public String[] getSslProtocols() {
212 return config.getSslProtocols();
213 }
214
215
216
217
218 @ManagedAttribute(description = "Defined SSL Ciphers")
219 public String[] getSslCiphers() {
220 return config.getSslCiphers();
221 }
222
223 @ManagedAttribute(description = "Component Type Name")
224 public String getComponentType() {
225 return getComponent().getClass().getName();
226 }
227
228 @ManagedAttribute(description = "Mina Host")
229 public String getHost() {
230 return getConfiguration().getHost();
231 }
232
233 @ManagedAttribute(description = "Mina Port")
234 public int getPort() {
235 return getConfiguration().getPort();
236 }
237
238 @ManagedAttribute(description = "Mina Character Set")
239 public String getCharsetName() {
240 return getConfiguration().getCharsetName();
241 }
242
243 @ManagedAttribute(description = "Mina Timeout")
244 public long getTimeout() {
245 return getConfiguration().getTimeout();
246 }
247
248 @ManagedAttribute(description = "Mina Filters")
249 public String[] getIoFilters() {
250 List<IoFilter> filters = getConfiguration().getFilters();
251 return toStringArray(filters);
252 }
253
254 @ManagedAttribute(description = "SSL Secure Enabled")
255 public boolean isSslSecure() {
256 return getSslContext() != null;
257 }
258
259
260
261
262 public ClientAuthType getClientAuthType() {
263 return config.getClientAuthType();
264 }
265
266 @ManagedAttribute(description = "Client Authentication Type")
267 public String getClientAuthTypeClass() {
268 return getClientAuthType().toString();
269 }
270
271
272
273
274 public List<InterceptorFactory> getCustomInterceptorFactories() {
275 return config.getCustomInterceptorFactories();
276 }
277
278 public ConsumerDispatchingInterceptor getDispatcher() {
279 return config.getDispatcher();
280 }
281
282
283
284
285
286 @ManagedAttribute(description = "Custom Interceptor Factories")
287 public String[] getCustomInterceptorFactoryList() {
288 return toStringArray(getCustomInterceptorFactories());
289 }
290
291 private String[] toStringArray(List<?> list) {
292 final String[] result = new String[list.size()];
293 for (int i = 0; i < list.size(); i++) {
294 result[i] = list.get(i).getClass().getCanonicalName();
295 }
296 return result;
297 }
298
299
300
301 @SuppressWarnings({"unchecked", "rawtypes"})
302 @Override
303 public void configureProperties(Map options) {
304 wrappedEndpoint.configureProperties(options);
305 }
306
307 @Override
308 public Exchange createExchange() {
309 return wrappedEndpoint.createExchange();
310 }
311
312 @Override
313 public Exchange createExchange(Exchange exchange) {
314 return wrappedEndpoint.createExchange(exchange);
315 }
316
317 @Override
318 public Exchange createExchange(ExchangePattern pattern) {
319 return wrappedEndpoint.createExchange(pattern);
320 }
321
322 @Override
323 public PollingConsumer createPollingConsumer() throws Exception {
324 return wrappedEndpoint.createPollingConsumer();
325 }
326
327 @Override
328 public boolean equals(Object object) {
329 if (object instanceof MllpEndpoint) {
330 MllpEndpoint<?, ?, ?> that = (MllpEndpoint<?, ?, ?>) object;
331 return wrappedEndpoint.equals(that.getWrappedEndpoint());
332 }
333 return false;
334 }
335
336 @Override
337 public CamelContext getCamelContext() {
338 return wrappedEndpoint.getCamelContext();
339 }
340
341 @Override
342 public Component getComponent() {
343 return wrappedEndpoint.getComponent();
344 }
345
346 public Mina2Configuration getConfiguration() {
347 return wrappedEndpoint.getConfiguration();
348 }
349
350 @Override
351 public String getEndpointKey() {
352 return wrappedEndpoint.getEndpointKey();
353 }
354
355 @Override
356 public String getEndpointUri() {
357 return wrappedEndpoint.getEndpointUri();
358 }
359
360 @Override
361 public ExchangePattern getExchangePattern() {
362 return wrappedEndpoint.getExchangePattern();
363 }
364
365 @Override
366 public int hashCode() {
367 return wrappedEndpoint.hashCode();
368 }
369
370 @Override
371 public boolean isLenientProperties() {
372 return wrappedEndpoint.isLenientProperties();
373 }
374
375 @Override
376 public boolean isSingleton() {
377 return wrappedEndpoint.isSingleton();
378 }
379
380 @Override
381 public void setCamelContext(CamelContext camelContext) {
382 wrappedEndpoint.setCamelContext(camelContext);
383 }
384
385 @Override
386 public void setEndpointUriIfNotSpecified(String value) {
387 wrappedEndpoint.setEndpointUriIfNotSpecified(value);
388 }
389
390 @Override
391 public void setExchangePattern(ExchangePattern exchangePattern) {
392 wrappedEndpoint.setExchangePattern(exchangePattern);
393 }
394
395 @Override
396 public String toString() {
397 return wrappedEndpoint.toString();
398 }
399
400 }