1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.openehealth.ipf.commons.ihe.ws;
17
18 import org.apache.cxf.endpoint.Client;
19 import org.apache.cxf.feature.AbstractFeature;
20 import org.apache.cxf.frontend.ClientProxy;
21 import org.apache.cxf.interceptor.InterceptorProvider;
22 import org.apache.cxf.transport.http.HTTPConduit;
23 import org.apache.cxf.ws.addressing.MAPAggregator;
24 import org.apache.cxf.ws.addressing.soap.MAPCodec;
25 import org.openehealth.ipf.commons.audit.AuditContext;
26 import org.openehealth.ipf.commons.ihe.core.atna.AuditStrategy;
27 import org.openehealth.ipf.commons.ihe.ws.correlation.AsynchronyCorrelator;
28 import org.openehealth.ipf.commons.ihe.ws.cxf.Cxf3791WorkaroundInterceptor;
29 import org.openehealth.ipf.commons.ihe.ws.cxf.FixContentTypeOutInterceptor;
30 import org.openehealth.ipf.commons.ihe.ws.cxf.MustUnderstandDecoratorInterceptor;
31 import org.openehealth.ipf.commons.ihe.ws.cxf.ProvidedAttachmentOutInterceptor;
32 import org.openehealth.ipf.commons.ihe.ws.cxf.audit.WsAuditDataset;
33 import org.openehealth.ipf.commons.ihe.ws.cxf.payload.OutPayloadExtractorInterceptor;
34 import org.openehealth.ipf.commons.ihe.ws.cxf.payload.OutStreamSubstituteInterceptor;
35 import org.openehealth.ipf.commons.ihe.ws.utils.SoapUtils;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 import javax.xml.namespace.QName;
40 import javax.xml.ws.Binding;
41 import javax.xml.ws.BindingProvider;
42 import javax.xml.ws.Service;
43 import javax.xml.ws.soap.SOAPBinding;
44 import java.net.URL;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.function.Supplier;
48
49 import static java.util.Objects.requireNonNull;
50
51
52
53
54
55
56 public class JaxWsClientFactory<AuditDatasetType extends WsAuditDataset> {
57 private static final Logger LOG = LoggerFactory.getLogger(JaxWsClientFactory.class);
58
59 protected final ThreadLocal<Object> threadLocalPort = new ThreadLocal<>();
60 protected final WsTransactionConfiguration<AuditDatasetType> wsTransactionConfiguration;
61 protected final String serviceUrl;
62 protected final InterceptorProvider customInterceptors;
63 protected final List<AbstractFeature> features;
64 protected final Map<String, Object> properties;
65 protected final AuditStrategy<AuditDatasetType> auditStrategy;
66 protected final AuditContext auditContext;
67 protected final AsynchronyCorrelator<AuditDatasetType> correlator;
68
69
70
71
72
73
74
75
76
77
78 public JaxWsClientFactory(
79 WsTransactionConfiguration<AuditDatasetType> wsTransactionConfiguration,
80 String serviceUrl,
81 AuditStrategy<AuditDatasetType> auditStrategy,
82 AuditContext auditContext,
83 InterceptorProvider customInterceptors,
84 List<AbstractFeature> features,
85 Map<String, Object> properties,
86 AsynchronyCorrelator<AuditDatasetType> correlator) {
87 requireNonNull(wsTransactionConfiguration, "wsTransactionConfiguration");
88 this.wsTransactionConfiguration = wsTransactionConfiguration;
89 this.serviceUrl = serviceUrl;
90 this.auditStrategy = auditStrategy;
91 this.auditContext = auditContext;
92 this.customInterceptors = customInterceptors;
93 this.features = features;
94 this.properties = properties;
95 this.correlator = correlator;
96 }
97
98
99
100
101
102
103
104 public synchronized Object getClient(Supplier<WsSecurityInformation> securityInformationSupplier) {
105 if (threadLocalPort.get() == null) {
106 URL wsdlURL = getClass().getClassLoader().getResource(wsTransactionConfiguration.getWsdlLocation());
107 Service service = Service.create(wsdlURL, wsTransactionConfiguration.getServiceName());
108 Object port = service.getPort(wsTransactionConfiguration.getSei());
109 Client client = ClientProxy.getClient(port);
110 configureBinding(port);
111 configureInterceptors(client);
112 configureProperties(client);
113 WsSecurityInformation securityInformation = securityInformationSupplier.get();
114 if (securityInformation != null) {
115 securityInformation.configureHttpConduit((HTTPConduit) client.getConduit());
116 }
117 threadLocalPort.set(port);
118 LOG.debug("Created client adapter for: {}", wsTransactionConfiguration.getServiceName());
119 }
120 return threadLocalPort.get();
121 }
122
123 public synchronized Object getClient() {
124 return getClient(() -> null);
125 }
126
127
128
129
130 public WsTransactionConfiguration<AuditDatasetType> getWsTransactionConfiguration() {
131 return wsTransactionConfiguration;
132 }
133
134
135
136
137
138 protected void configureInterceptors(Client client) {
139 client.getInInterceptors().add(new Cxf3791WorkaroundInterceptor());
140
141
142 if (wsTransactionConfiguration.isAddressing()) {
143 MustUnderstandDecoratorInterceptor interceptor = new MustUnderstandDecoratorInterceptor();
144 for (String nsUri : SoapUtils.WS_ADDRESSING_NS_URIS) {
145 interceptor.addHeader(new QName(nsUri, "Action"));
146 }
147
148 client.getOutInterceptors().add(interceptor);
149
150 MAPCodec mapCodec = new MAPCodec();
151 MAPAggregator mapAggregator = new MAPAggregator();
152 client.getInInterceptors().add(mapCodec);
153 client.getInInterceptors().add(mapAggregator);
154 client.getInFaultInterceptors().add(mapCodec);
155 client.getInFaultInterceptors().add(mapAggregator);
156 client.getOutInterceptors().add(mapCodec);
157 client.getOutInterceptors().add(mapAggregator);
158 client.getOutFaultInterceptors().add(mapCodec);
159 client.getOutFaultInterceptors().add(mapAggregator);
160 }
161
162 if (wsTransactionConfiguration.isSwaOutSupport()) {
163 client.getOutInterceptors().add(new ProvidedAttachmentOutInterceptor());
164 client.getOutInterceptors().add(new FixContentTypeOutInterceptor());
165 }
166
167 if (features != null) {
168 for (AbstractFeature feature : features) {
169 client.getEndpoint().getActiveFeatures().add(feature);
170 feature.initialize(client, client.getBus());
171 }
172 }
173
174 InterceptorUtils.copyInterceptorsFromProvider(customInterceptors, client);
175
176 }
177
178 protected void configureProperties(Client client) {
179 if (properties != null) {
180 client.getEndpoint().putAll(properties);
181 }
182 }
183
184
185
186
187
188 static protected void installPayloadInterceptors(Client client) {
189 client.getOutInterceptors().add(new OutStreamSubstituteInterceptor());
190 client.getOutInterceptors().add(new OutPayloadExtractorInterceptor());
191 }
192
193
194
195
196
197 private void configureBinding(Object port) {
198 BindingProvider bindingProvider = (BindingProvider) port;
199
200 Map<String, Object> reqContext = bindingProvider.getRequestContext();
201 reqContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, serviceUrl);
202
203 Binding binding = bindingProvider.getBinding();
204 SOAPBinding soapBinding = (SOAPBinding) binding;
205 soapBinding.setMTOMEnabled(wsTransactionConfiguration.isMtom());
206 }
207 }