Merge "Fix Blocker/Critical sonar issues"
[aai/sparky-be.git] / src / main / java / org / openecomp / sparky / dal / rest / RestfulDataAccessor.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017 Amdocs
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  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  */
23 package org.openecomp.sparky.dal.rest;
24
25 import java.security.SecureRandom;
26
27 import org.openecomp.cl.api.Logger;
28 import org.openecomp.cl.eelf.LoggerFactory;
29 import org.openecomp.sparky.dal.cache.EntityCache;
30 import org.openecomp.sparky.logging.AaiUiMsgs;
31 import org.openecomp.sparky.util.NodeUtils;
32
33 import com.sun.jersey.api.client.Client;
34 import com.sun.jersey.api.client.ClientResponse;
35 import com.sun.jersey.api.client.WebResource;
36 import com.sun.jersey.api.client.WebResource.Builder;
37
38 /**
39  * The Class RestfulDataAccessor.
40  */
41 public class RestfulDataAccessor implements RestDataProvider {
42
43   protected SecureRandom txnIdGenerator;
44
45   protected RestClientBuilder clientBuilder;
46
47   protected EntityCache entityCache;
48   private boolean cacheEnabled;
49   private static final Logger LOG =
50       LoggerFactory.getInstance().getLogger(RestfulDataAccessor.class);
51
52   private boolean resourceNotFoundErrorsSurpressed;
53
54   public static final String APPLICATION_JSON = "application/json";
55   public static final String APPLICATION_MERGE_PATCH_JSON = "application/merge-patch+json";
56   public static final String APPLICATION_X_WWW_FORM_URL_ENCODED =
57       "application/x-www-form-urlencoded";
58
59
60   /**
61    * Instantiates a new restful data accessor.
62    *
63    * @param clientBuilder the client builder
64    */
65   public RestfulDataAccessor(RestClientBuilder clientBuilder) {
66     this.clientBuilder = clientBuilder;
67     txnIdGenerator = new SecureRandom();
68     resourceNotFoundErrorsSurpressed = false;
69     cacheEnabled = false;
70     entityCache = null;
71   }
72
73   protected boolean isCacheEnabled() {
74     return cacheEnabled;
75   }
76
77   public void setCacheEnabled(boolean cacheEnabled) {
78     this.cacheEnabled = cacheEnabled;
79   }
80
81   protected EntityCache getEntityCache() {
82     return entityCache;
83   }
84
85   public void setEntityCache(EntityCache entityCache) {
86     this.entityCache = entityCache;
87   }
88
89   /**
90    * Cache result.
91    *
92    * @param result the result
93    */
94   private void cacheResult(OperationResult result) {
95     if (cacheEnabled && entityCache != null) {
96       final String id =
97           NodeUtils.generateUniqueShaDigest(result.getRequestLink(), result.getRequestPayload());
98       entityCache.put(id, result);
99     }
100   }
101
102   /**
103    * Populate operation result.
104    *
105    * @param response the response
106    * @param opResult the op result
107    */
108   protected void populateOperationResult(ClientResponse response, OperationResult opResult) {
109
110     if (response == null) {
111       opResult.setResult(500, "Client response was null");
112       return;
113     }
114
115     int statusCode = response.getStatus();
116     String payload = response.getEntity(String.class);
117
118     opResult.setResult(statusCode, payload);
119
120   }
121
122   /**
123    * Gets the cached data.
124    *
125    * @param link the link
126    * @param payload the payload
127    * @return the cached data
128    */
129   private OperationResult getCachedData(String link, String payload) {
130     if (cacheEnabled && entityCache != null) {
131       final String id = NodeUtils.generateUniqueShaDigest(link, payload);
132       return entityCache.get(id, link);
133     }
134     return null;
135   }
136
137   /* (non-Javadoc)
138    * @see org.openecomp.sparky.dal.rest.RestDataProvider#doRestfulOperation(org.openecomp.sparky.dal.rest.HttpMethod, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
139    */
140   @Override
141   public OperationResult doRestfulOperation(HttpMethod method, String url, String payload,
142       String payloadType, String acceptContentType) {
143
144     ClientResponse clientResponse = null;
145
146     long startTimeInMs = System.currentTimeMillis();
147     Client client = null;
148     Builder builder = null;
149
150     OperationResult operationResult = null;
151
152     /*
153      * Attempt to get cached data for the requested URL. We don't currently cache the other
154      * operations.
155      */
156
157     operationResult = getCachedData(url, payload);
158
159     if (operationResult != null) {
160
161       /*
162        * cache-hit, return what we found
163        */
164
165       // System.out.println("operationResult = " + operationResult.getResultCode());
166       // System.out.println("opresult = " + operationResult.getResult());
167       return operationResult;
168     }
169
170     /*
171      * else cache miss / cache disabled (default operation)
172      */
173
174     operationResult = new OperationResult();
175     operationResult.setRequestLink(url);
176
177     try {
178
179       client = clientBuilder.getClient();
180
181       switch (method) {
182         case GET: {
183           builder = setClientDefaults(client, url, null, acceptContentType);
184           clientResponse = builder.get(ClientResponse.class);
185           break;
186         }
187
188         case PUT: {
189           builder = setClientDefaults(client, url, payloadType, acceptContentType);
190           clientResponse = builder.put(ClientResponse.class, payload);
191           break;
192         }
193
194         case POST: {
195           builder = setClientDefaults(client, url, payloadType, acceptContentType);
196           clientResponse = builder.post(ClientResponse.class, payload);
197           break;
198         }
199
200         case DELETE: {
201           builder = setClientDefaults(client, url, null, acceptContentType);
202           clientResponse = builder.delete(ClientResponse.class);
203           break;
204         }
205
206         case PATCH: {
207           builder = setClientDefaults(client, url, payloadType, acceptContentType);
208           builder = builder.header("X-HTTP-Method-Override", "PATCH");
209           clientResponse = builder.post(ClientResponse.class, payload);
210           break;
211         }
212
213         case HEAD: {
214           builder = setClientDefaults(client, url, null, acceptContentType);
215           clientResponse = builder.head();
216           break;
217         }
218
219
220         default: {
221           operationResult.setResult(500, "Unhandled HTTP Method operation = " + method);
222           return operationResult;
223         }
224
225       }
226
227     } catch (Exception ex) {
228       LOG.error(AaiUiMsgs.RESTFULL_OP_ERROR_VERBOSE, url, ex.getLocalizedMessage());
229       operationResult.setResult(500,
230           String.format("Error retrieving link = '%s' from restful endpoint due to error = '%s'",
231               url, ex.getLocalizedMessage()));
232       return operationResult;
233     }
234
235     populateOperationResult(clientResponse, operationResult);
236
237     if (operationResult.getResultCode() != 404
238         || (operationResult.getResultCode() == 404 && !isResourceNotFoundErrorsSurpressed())) {
239       LOG.info(AaiUiMsgs.RESTFULL_OP_COMPLETE, method.toString(),
240           String.valueOf(System.currentTimeMillis() - startTimeInMs), url,
241           String.valueOf(operationResult.getResultCode()));
242     }
243
244     cacheResult(operationResult);
245
246     return operationResult;
247
248   }
249
250   public boolean isResourceNotFoundErrorsSurpressed() {
251     return resourceNotFoundErrorsSurpressed;
252   }
253
254   public void setResourceNotFoundErrorsSurpressed(boolean resourceNotFoundErrorsSurpressed) {
255     this.resourceNotFoundErrorsSurpressed = resourceNotFoundErrorsSurpressed;
256   }
257
258   /* (non-Javadoc)
259    * @see org.openecomp.sparky.dal.rest.RestDataProvider#doGet(java.lang.String, java.lang.String)
260    */
261   @Override
262   public OperationResult doGet(String url, String acceptContentType) {
263     return doRestfulOperation(HttpMethod.GET, url, null, null, acceptContentType);
264   }
265
266   /* (non-Javadoc)
267    * @see org.openecomp.sparky.dal.rest.RestDataProvider#doDelete(java.lang.String, java.lang.String)
268    */
269   @Override
270   public OperationResult doDelete(String url, String acceptContentType) {
271     return doRestfulOperation(HttpMethod.DELETE, url, null, null, acceptContentType);
272   }
273
274   /* (non-Javadoc)
275    * @see org.openecomp.sparky.dal.rest.RestDataProvider#doPost(java.lang.String, java.lang.String, java.lang.String)
276    */
277   @Override
278   public OperationResult doPost(String url, String jsonPayload, String acceptContentType) {
279     return doRestfulOperation(HttpMethod.POST, url, jsonPayload, APPLICATION_JSON,
280         acceptContentType);
281   }
282
283   /* (non-Javadoc)
284    * @see org.openecomp.sparky.dal.rest.RestDataProvider#doPut(java.lang.String, java.lang.String, java.lang.String)
285    */
286   @Override
287   public OperationResult doPut(String url, String jsonPayload, String acceptContentType) {
288     return doRestfulOperation(HttpMethod.PUT, url, jsonPayload, APPLICATION_JSON,
289         acceptContentType);
290   }
291
292   /* (non-Javadoc)
293    * @see org.openecomp.sparky.dal.rest.RestDataProvider#doPatch(java.lang.String, java.lang.String, java.lang.String)
294    */
295   @Override
296   public OperationResult doPatch(String url, String jsonPayload, String acceptContentType) {
297     return doRestfulOperation(HttpMethod.PATCH, url, jsonPayload, APPLICATION_MERGE_PATCH_JSON,
298         acceptContentType);
299   }
300
301   /* (non-Javadoc)
302    * @see org.openecomp.sparky.dal.rest.RestDataProvider#doHead(java.lang.String, java.lang.String)
303    */
304   @Override
305   public OperationResult doHead(String url, String acceptContentType) {
306     return doRestfulOperation(HttpMethod.HEAD, url, null, null, acceptContentType);
307   }
308
309   /**
310    * Sets the client defaults.
311    *
312    * @param client the client
313    * @param url the url
314    * @param payloadContentType the payload content type
315    * @param acceptContentType the accept content type
316    * @return the builder
317    */
318   protected Builder setClientDefaults(Client client, String url, String payloadContentType,
319       String acceptContentType) {
320     WebResource resource = client.resource(url);
321     Builder builder = null;
322     builder = resource.accept(acceptContentType);
323
324     if (payloadContentType != null) {
325       builder = builder.header("Content-Type", payloadContentType);
326     }
327
328     return builder;
329   }
330
331   /* (non-Javadoc)
332    * @see org.openecomp.sparky.dal.rest.RestDataProvider#shutdown()
333    */
334   @Override
335   public void shutdown() {
336
337     if (entityCache != null) {
338       entityCache.shutdown();
339     }
340
341   }
342
343   /* (non-Javadoc)
344    * @see org.openecomp.sparky.dal.rest.RestDataProvider#clearCache()
345    */
346   @Override
347   public void clearCache() {
348     if (cacheEnabled) {
349       entityCache.clear();
350     }
351
352   }
353
354 }