38ec6829d170c245c840c734d3b01c1bafe0d6e5
[policy/common.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2018 Samsung Electronics Co., Ltd.
7  * Modifications Copyright (C) 2019 Nordix Foundation.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.common.endpoints.http.client.internal;
24
25 import com.fasterxml.jackson.annotation.JsonIgnore;
26 import java.security.KeyManagementException;
27 import java.security.NoSuchAlgorithmException;
28 import java.security.SecureRandom;
29 import java.util.Collections;
30 import java.util.Map;
31 import java.util.Map.Entry;
32 import java.util.concurrent.Future;
33 import javax.net.ssl.SSLContext;
34 import javax.ws.rs.client.Client;
35 import javax.ws.rs.client.ClientBuilder;
36 import javax.ws.rs.client.Entity;
37 import javax.ws.rs.client.Invocation.Builder;
38 import javax.ws.rs.client.InvocationCallback;
39 import javax.ws.rs.core.Response;
40 import org.apache.commons.lang3.StringUtils;
41 import org.glassfish.jersey.client.ClientProperties;
42 import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
43 import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
44 import org.onap.policy.common.endpoints.http.client.HttpClient;
45 import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
46 import org.onap.policy.common.utils.network.NetworkUtil;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 /**
51  * Http Client implementation using a Jersey Client.
52  */
53 public class JerseyClient implements HttpClient {
54
55     /**
56      * Logger.
57      */
58     private static Logger logger = LoggerFactory.getLogger(JerseyClient.class);
59
60     protected static final String JERSEY_DEFAULT_SERIALIZATION_PROVIDER =
61                     "org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJsonProvider";
62
63     protected final String name;
64     protected final boolean https;
65     protected final boolean selfSignedCerts;
66     protected final String hostname;
67     protected final int port;
68     protected final String basePath;
69     protected final String userName;
70     protected final String password;
71
72     protected final Client client;
73     protected final String baseUrl;
74
75     protected boolean alive = true;
76
77     /**
78      * Constructor.
79      *
80      * <p>name the name https is it https or not selfSignedCerts are there self signed certs
81      * hostname the hostname port port being used basePath base context userName user
82      * password password
83      *
84      * @param busTopicParams Input parameters object
85      * @throws KeyManagementException key exception
86      * @throws NoSuchAlgorithmException no algorithm exception
87      * @throws ClassNotFoundException if the serialization provider cannot be found
88      */
89     public JerseyClient(BusTopicParams busTopicParams)
90                     throws KeyManagementException, NoSuchAlgorithmException, ClassNotFoundException {
91
92         if (busTopicParams.isClientNameInvalid()) {
93             throw new IllegalArgumentException("Name must be provided");
94         }
95
96         if (busTopicParams.isHostnameInvalid()) {
97             throw new IllegalArgumentException("Hostname must be provided");
98         }
99
100         if (busTopicParams.isPortInvalid()) {
101             throw new IllegalArgumentException("Invalid Port provided: " + busTopicParams.getPort());
102         }
103
104         this.name = busTopicParams.getClientName();
105         this.https = busTopicParams.isUseHttps();
106         this.hostname = busTopicParams.getHostname();
107         this.port = busTopicParams.getPort();
108         this.basePath = busTopicParams.getBasePath();
109         this.userName = busTopicParams.getUserName();
110         this.password = busTopicParams.getPassword();
111         this.selfSignedCerts = busTopicParams.isAllowSelfSignedCerts();
112         this.client = detmClient();
113
114         if (!StringUtils.isBlank(this.userName) && !StringUtils.isBlank(this.password)) {
115             HttpAuthenticationFeature authFeature = HttpAuthenticationFeature.basic(userName, password);
116             this.client.register(authFeature);
117         }
118
119         this.client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true");
120
121         registerSerProviders(busTopicParams.getSerializationProvider());
122
123         this.baseUrl = (this.https ? "https://" : "http://") + this.hostname + ":" + this.port + "/"
124                         + (this.basePath == null ? "" : this.basePath);
125     }
126
127     private Client detmClient() throws NoSuchAlgorithmException, KeyManagementException {
128         if (this.https) {
129             ClientBuilder clientBuilder;
130             SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
131             if (this.selfSignedCerts) {
132                 sslContext.init(null, NetworkUtil.getAlwaysTrustingManager(), new SecureRandom());
133                 clientBuilder =
134                         ClientBuilder.newBuilder().sslContext(sslContext).hostnameVerifier((host, session) -> true);
135             } else {
136                 sslContext.init(null, null, null);
137                 clientBuilder = ClientBuilder.newBuilder().sslContext(sslContext);
138             }
139             return clientBuilder.build();
140
141         } else {
142             return ClientBuilder.newClient();
143         }
144     }
145
146     /**
147      * Registers the serialization provider(s) with the client.
148      *
149      * @param serializationProvider comma-separated list of serialization providers
150      * @throws ClassNotFoundException if the serialization provider cannot be found
151      */
152     private void registerSerProviders(String serializationProvider) throws ClassNotFoundException {
153         String providers = (StringUtils.isBlank(serializationProvider)
154                         ? JERSEY_DEFAULT_SERIALIZATION_PROVIDER : serializationProvider);
155         for (String prov : providers.split(",")) {
156             this.client.register(Class.forName(prov));
157         }
158     }
159
160     @Override
161     public Response get(String path) {
162         if (!StringUtils.isBlank(path)) {
163             return this.client.target(this.baseUrl).path(path).request().get();
164         } else {
165             return this.client.target(this.baseUrl).request().get();
166         }
167     }
168
169     @Override
170     public Response get() {
171         return this.client.target(this.baseUrl).request().get();
172     }
173
174     @Override
175     public Future<Response> get(InvocationCallback<Response> callback, String path, Map<String, Object> headers) {
176         Map<String, Object> headers2 = (headers != null ? headers : Collections.emptyMap());
177
178         if (!StringUtils.isBlank(path)) {
179             return getBuilder(path, headers2).async().get(callback);
180         } else {
181             return get(callback, headers2);
182         }
183     }
184
185     @Override
186     public Future<Response> get(InvocationCallback<Response> callback, Map<String, Object> headers) {
187         Builder builder = this.client.target(this.baseUrl).request();
188         if (headers != null) {
189             headers.forEach(builder::header);
190         }
191         return builder.async().get(callback);
192     }
193
194     @Override
195     public Response put(String path, Entity<?> entity, Map<String, Object> headers) {
196         return getBuilder(path, headers).put(entity);
197     }
198
199     @Override
200     public Future<Response> put(InvocationCallback<Response> callback, String path, Entity<?> entity,
201                     Map<String, Object> headers) {
202         return getBuilder(path, headers).async().put(entity, callback);
203     }
204
205     @Override
206     public Response post(String path, Entity<?> entity, Map<String, Object> headers) {
207         return getBuilder(path, headers).post(entity);
208     }
209
210     @Override
211     public Future<Response> post(InvocationCallback<Response> callback, String path, Entity<?> entity,
212                     Map<String, Object> headers) {
213         return getBuilder(path, headers).async().post(entity, callback);
214     }
215
216     @Override
217     public Response delete(String path, Map<String, Object> headers) {
218         return getBuilder(path, headers).delete();
219     }
220
221     @Override
222     public Future<Response> delete(InvocationCallback<Response> callback, String path, Map<String, Object> headers) {
223         return getBuilder(path, headers).async().delete(callback);
224     }
225
226     @Override
227     public boolean start() {
228         return alive;
229     }
230
231     @Override
232     public boolean stop() {
233         return !alive;
234     }
235
236     @Override
237     public void shutdown() {
238         synchronized (this) {
239             alive = false;
240         }
241
242         try {
243             this.client.close();
244         } catch (Exception e) {
245             logger.warn("{}: cannot close because of {}", this, e.getMessage(), e);
246         }
247     }
248
249     @Override
250     public synchronized boolean isAlive() {
251         return this.alive;
252     }
253
254     @Override
255     public String getName() {
256         return name;
257     }
258
259     @Override
260     public boolean isHttps() {
261         return https;
262     }
263
264     @Override
265     public boolean isSelfSignedCerts() {
266         return selfSignedCerts;
267     }
268
269     @Override
270     public String getHostname() {
271         return hostname;
272     }
273
274     @Override
275     public int getPort() {
276         return port;
277     }
278
279     @Override
280     public String getBasePath() {
281         return basePath;
282     }
283
284     @Override
285     public String getUserName() {
286         return userName;
287     }
288
289     @JsonIgnore
290     @GsonJsonIgnore
291     @Override
292     public String getPassword() {
293         return password;
294     }
295
296     @Override
297     public String getBaseUrl() {
298         return baseUrl;
299     }
300
301     @Override
302     public String toString() {
303         StringBuilder builder = new StringBuilder();
304         builder.append("JerseyClient [name=");
305         builder.append(name);
306         builder.append(", https=");
307         builder.append(https);
308         builder.append(", selfSignedCerts=");
309         builder.append(selfSignedCerts);
310         builder.append(", hostname=");
311         builder.append(hostname);
312         builder.append(", port=");
313         builder.append(port);
314         builder.append(", basePath=");
315         builder.append(basePath);
316         builder.append(", userName=");
317         builder.append(userName);
318         builder.append(", password=");
319         builder.append(password);
320         builder.append(", client=");
321         builder.append(client);
322         builder.append(", baseUrl=");
323         builder.append(baseUrl);
324         builder.append(", alive=");
325         builder.append(alive);
326         builder.append("]");
327         return builder.toString();
328     }
329
330     private Builder getBuilder(String path, Map<String, Object> headers) {
331         Builder builder = this.client.target(this.baseUrl).path(path).request();
332         for (Entry<String, Object> header : headers.entrySet()) {
333             builder.header(header.getKey(), header.getValue());
334         }
335         return builder;
336     }
337
338
339 }