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