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