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