2287486e1362f9fcfb0591d6b68f23a298a68aff
[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.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 /**
48  * Http Client implementation using a Jersey Client.
49  * 
50  * <p>Note: the serialization provider will be ignored if the maven artifact,
51  * <i>jersey-media-json-jackson</i>, is included, regardless of whether it's included
52  * directly or indirectly.
53  */
54 public class JerseyClient implements HttpClient {
55
56     /**
57      * Logger.
58      */
59     private static Logger logger = LoggerFactory.getLogger(JerseyClient.class);
60     
61     protected static final String JERSEY_DEFAULT_SERIALIZATION_PROVIDER =
62                     "com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider";
63
64     protected final String name;
65     protected final boolean https;
66     protected final boolean selfSignedCerts;
67     protected final String hostname;
68     protected final int port;
69     protected final String basePath;
70     protected final String userName;
71     protected final String password;
72
73     protected final Client client;
74     protected final String baseUrl;
75
76     protected boolean alive = true;
77
78     /**
79      * Constructor.
80      * 
81      * <p>name the name https is it https or not selfSignedCerts are there self signed certs
82      * hostname the hostname port port being used basePath base context userName user
83      * password password
84      * 
85      * @param busTopicParams Input parameters object
86      * @throws KeyManagementException key exception
87      * @throws NoSuchAlgorithmException no algorithm exception
88      * @throws ClassNotFoundException if the serialization provider cannot be found
89      */
90     public JerseyClient(BusTopicParams busTopicParams)
91                     throws KeyManagementException, NoSuchAlgorithmException, ClassNotFoundException {
92
93         super();
94
95         if (busTopicParams.isClientNameInvalid()) {
96             throw new IllegalArgumentException("Name must be provided");
97         }
98
99         if (busTopicParams.isHostnameInvalid()) {
100             throw new IllegalArgumentException("Hostname must be provided");
101         }
102
103         if (busTopicParams.isPortInvalid()) {
104             throw new IllegalArgumentException("Invalid Port provided: " + busTopicParams.getPort());
105         }
106
107         this.name = busTopicParams.getClientName();
108         this.https = busTopicParams.isUseHttps();
109         this.hostname = busTopicParams.getHostname();
110         this.port = busTopicParams.getPort();
111         this.basePath = busTopicParams.getBasePath();
112         this.userName = busTopicParams.getUserName();
113         this.password = busTopicParams.getPassword();
114         this.selfSignedCerts = busTopicParams.isAllowSelfSignedCerts();
115
116         StringBuilder tmpBaseUrl = new StringBuilder();
117         if (this.https) {
118             tmpBaseUrl.append("https://");
119             ClientBuilder clientBuilder;
120             SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
121             if (this.selfSignedCerts) {
122                 sslContext.init(null, new TrustManager[] {new X509TrustManager() {
123                     @Override
124                     public void checkClientTrusted(X509Certificate[] chain, String authType)
125                             throws CertificateException {
126                         // always trusted
127                     }
128
129                     @Override
130                     public void checkServerTrusted(X509Certificate[] chain, String authType)
131                             throws CertificateException {
132                         // always trusted
133                     }
134
135                     @Override
136                     public X509Certificate[] getAcceptedIssuers() {
137                         return new X509Certificate[0];
138                     }
139
140                 } }, new SecureRandom());
141                 clientBuilder =
142                         ClientBuilder.newBuilder().sslContext(sslContext).hostnameVerifier((host, session) -> true);
143             } else {
144                 sslContext.init(null, null, null);
145                 clientBuilder = ClientBuilder.newBuilder().sslContext(sslContext);
146             }
147             this.client = clientBuilder.build();
148         } else {
149             tmpBaseUrl.append("http://");
150             this.client = ClientBuilder.newClient();
151         }
152
153         if (this.userName != null && !this.userName.isEmpty() && this.password != null && !this.password.isEmpty()) {
154             HttpAuthenticationFeature authFeature = HttpAuthenticationFeature.basic(userName, password);
155             this.client.register(authFeature);
156         }
157
158         registerSerProviders(busTopicParams.getSerializationProvider());
159         
160         this.client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true");
161
162         this.baseUrl = tmpBaseUrl.append(this.hostname).append(":").append(this.port).append("/")
163                 .append((this.basePath == null) ? "" : this.basePath).toString();
164     }
165
166     /**
167      * Registers the serialization provider(s) with the client.
168      * 
169      * @param serializationProvider comma-separated list of serialization providers
170      * @throws ClassNotFoundException if the serialization provider cannot be found
171      */
172     private void registerSerProviders(String serializationProvider) throws ClassNotFoundException {
173         String providers = (serializationProvider == null || serializationProvider.isEmpty()
174                         ? JERSEY_DEFAULT_SERIALIZATION_PROVIDER : serializationProvider);
175         for (String prov : providers.split(",")) {
176             this.client.register(Class.forName(prov));
177         }
178     }
179
180     @Override
181     public Response get(String path) {
182         if (path != null && !path.isEmpty()) {
183             return this.client.target(this.baseUrl).path(path).request().get();
184         } else {
185             return this.client.target(this.baseUrl).request().get();
186         }
187     }
188
189     @Override
190     public Response get() {
191         return this.client.target(this.baseUrl).request().get();
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 Response post(String path, Entity<?> entity, Map<String, Object> headers) {
201         return getBuilder(path, headers).post(entity);
202     }
203
204     @Override
205     public Response delete(String path, Map<String, Object> headers) {
206         return getBuilder(path, headers).delete();
207     }
208
209     @Override
210     public boolean start() {
211         return alive;
212     }
213
214     @Override
215     public boolean stop() {
216         return !alive;
217     }
218
219     @Override
220     public void shutdown() {
221         synchronized (this) {
222             alive = false;
223         }
224
225         try {
226             this.client.close();
227         } catch (Exception e) {
228             logger.warn("{}: cannot close because of {}", this, e.getMessage(), e);
229         }
230     }
231
232     @Override
233     public synchronized boolean isAlive() {
234         return this.alive;
235     }
236
237     @Override
238     public String getName() {
239         return name;
240     }
241
242     @Override
243     public boolean isHttps() {
244         return https;
245     }
246
247     @Override
248     public boolean isSelfSignedCerts() {
249         return selfSignedCerts;
250     }
251
252     @Override
253     public String getHostname() {
254         return hostname;
255     }
256
257     @Override
258     public int getPort() {
259         return port;
260     }
261
262     @Override
263     public String getBasePath() {
264         return basePath;
265     }
266
267     @Override
268     public String getUserName() {
269         return userName;
270     }
271
272     @JsonIgnore
273     @Override
274     public String getPassword() {
275         return password;
276     }
277
278     @Override
279     public String getBaseUrl() {
280         return baseUrl;
281     }
282
283     @Override
284     public String toString() {
285         StringBuilder builder = new StringBuilder();
286         builder.append("JerseyClient [name=");
287         builder.append(name);
288         builder.append(", https=");
289         builder.append(https);
290         builder.append(", selfSignedCerts=");
291         builder.append(selfSignedCerts);
292         builder.append(", hostname=");
293         builder.append(hostname);
294         builder.append(", port=");
295         builder.append(port);
296         builder.append(", basePath=");
297         builder.append(basePath);
298         builder.append(", userName=");
299         builder.append(userName);
300         builder.append(", password=");
301         builder.append(password);
302         builder.append(", client=");
303         builder.append(client);
304         builder.append(", baseUrl=");
305         builder.append(baseUrl);
306         builder.append(", alive=");
307         builder.append(alive);
308         builder.append("]");
309         return builder.toString();
310     }
311
312     private Builder getBuilder(String path, Map<String, Object> headers) {
313         Builder builder = this.client.target(this.baseUrl).path(path).request();
314         for (Entry<String, Object> header : headers.entrySet()) {
315             builder.header(header.getKey(), header.getValue());
316         }
317         return builder;
318     }
319
320
321 }