Convert aai-service provider to blueprint
[ccsdk/sli/adaptors.git] / aai-service / provider / src / main / java / org / onap / ccsdk / sli / adaptors / aai / AAIClientRESTExecutor.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                         reserved.
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.ccsdk.sli.adaptors.aai;
23
24 import java.io.BufferedReader;
25 import java.io.ByteArrayInputStream;
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.InputStream;
29 import java.io.InputStreamReader;
30 import java.io.OutputStreamWriter;
31 import java.lang.reflect.Field;
32 import java.lang.reflect.InvocationTargetException;
33 import java.lang.reflect.Method;
34 import java.lang.reflect.Modifier;
35 import java.net.HttpURLConnection;
36 import java.net.MalformedURLException;
37 import java.net.URL;
38 import java.nio.charset.StandardCharsets;
39 import java.security.KeyManagementException;
40 import java.security.KeyStore;
41 import java.security.NoSuchAlgorithmException;
42 import java.text.SimpleDateFormat;
43 import java.util.Properties;
44
45 import javax.net.ssl.HostnameVerifier;
46 import javax.net.ssl.HttpsURLConnection;
47 import javax.net.ssl.KeyManagerFactory;
48 import javax.net.ssl.SSLContext;
49 import javax.net.ssl.SSLSession;
50 import javax.net.ssl.SSLSocketFactory;
51 import javax.ws.rs.HttpMethod;
52
53 import org.apache.commons.codec.binary.Base64;
54 import org.onap.ccsdk.sli.adaptors.aai.AAIService.TransactionIdTracker;
55 import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
56 import org.onap.ccsdk.sli.adaptors.aai.data.ErrorResponse;
57 import org.onap.ccsdk.sli.adaptors.aai.data.RequestError;
58 import org.onap.ccsdk.sli.adaptors.aai.data.ResourceVersion;
59 import org.onap.ccsdk.sli.adaptors.aai.data.ServiceException;
60 import org.onap.ccsdk.sli.core.sli.MetricLogger;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 import com.fasterxml.jackson.databind.DeserializationFeature;
65 import com.fasterxml.jackson.databind.ObjectMapper;
66 import com.sun.jersey.api.client.config.DefaultClientConfig;
67 import com.sun.jersey.client.urlconnection.HTTPSProperties;
68
69 /**
70  * The AAIClientRESTExecutor class provides CRUD API for AAI Client service.
71  * @author  richtabedzki
72  */
73 public     class AAIClientRESTExecutor implements AAIExecutorInterface {
74
75     private final String truststorePath;
76     private final String truststorePassword;
77     private final String keystorePath;
78     private final String keystorePassword;
79     private final Boolean ignoreCertificateHostError;
80     // authentication credentials
81     private String userName;
82     private String userPassword;
83     private final String applicationId;
84
85     /**
86      * class Constructor
87      * @param props - properties to initialize an instance.
88      */
89     public AAIClientRESTExecutor(Properties props) {
90         super();
91
92         userName            = props.getProperty(AAIService.CLIENT_NAME);
93         userPassword        = props.getProperty(AAIService.CLIENT_PWWD);
94
95         if(userName == null || userName.isEmpty()){
96             LOG.debug("Basic user name is not set");
97         }
98         if(userPassword == null || userPassword.isEmpty()) {
99             LOG.debug("Basic password is not set");
100         }
101
102         truststorePath     = props.getProperty(AAIService.TRUSTSTORE_PATH);
103         truststorePassword = props.getProperty(AAIService.TRUSTSTORE_PSSWD);
104         keystorePath         = props.getProperty(AAIService.KEYSTORE_PATH);
105         keystorePassword     = props.getProperty(AAIService.KEYSTORE_PSSWD);
106 //        this.read_timeout = read_timeout;
107
108         String tmpApplicationId =props.getProperty(AAIService.APPLICATION_ID);
109         if(tmpApplicationId == null || tmpApplicationId.isEmpty()) {
110             tmpApplicationId = "SDNC";
111         }
112         applicationId = tmpApplicationId;
113
114         String iche = props.getProperty(AAIService.CERTIFICATE_HOST_ERROR);
115         boolean host_error = false;
116         if(iche != null && !iche.isEmpty()) {
117             host_error = Boolean.valueOf(iche);
118         }
119
120         ignoreCertificateHostError = host_error;
121
122         HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier(){
123             public boolean verify(String string,SSLSession ssls) {
124                 return ignoreCertificateHostError;
125             }
126         });
127
128         if(truststorePath != null && truststorePassword != null && (new File(truststorePath)).exists()) {
129             System.setProperty("javax.net.ssl.trustStore", truststorePath);
130             System.setProperty("javax.net.ssl.trustStorePassword", truststorePassword);
131         }
132
133         if(keystorePath != null && keystorePassword != null && (new File(keystorePath)).exists())
134         {
135             DefaultClientConfig config = new DefaultClientConfig();
136             //both jersey and HttpURLConnection can use this
137             SSLContext ctx = null;
138             try {
139                 ctx = SSLContext.getInstance("TLS");
140
141                 KeyManagerFactory kmf = null;
142                 try {
143                     String storeType = "PKCS12";
144                     String def = KeyStore.getDefaultType();
145                     kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
146                     FileInputStream fin = new FileInputStream(keystorePath);
147
148                     String extension = keystorePath.substring(keystorePath.lastIndexOf(".") + 1);
149
150                     if(extension != null && !extension.isEmpty() && extension.equalsIgnoreCase("JKS")) {
151                         storeType = "JKS";
152                     }
153                     KeyStore ks = KeyStore.getInstance(storeType);
154
155                     char[] pwd = keystorePassword.toCharArray();
156                     ks.load(fin, pwd);
157                     kmf.init(ks, pwd);
158                 } catch (Exception ex) {
159                     LOG.error("AAIResource", ex);
160                 }
161
162                 ctx.init(kmf.getKeyManagers(), null, null);
163                 config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties( new HostnameVerifier() {
164                         @Override
165                         public boolean verify( String s, SSLSession sslSession ) {
166                             return ignoreCertificateHostError;
167                         }
168                 }, ctx));
169
170                 CTX = ctx;
171                 LOG.debug("SSLContext created");
172
173             } catch (KeyManagementException | NoSuchAlgorithmException exc) {
174                 LOG.error("AAIResource", exc);
175             }
176         }
177
178         try {
179             Field methodsField = HttpURLConnection.class.getDeclaredField("methods");
180             methodsField.setAccessible(true);
181             // get the methods field modifiers
182             Field modifiersField = Field.class.getDeclaredField("modifiers");
183             // bypass the "private" modifier
184             modifiersField.setAccessible(true);
185
186             // remove the "final" modifier
187             modifiersField.setInt(methodsField, methodsField.getModifiers() & ~Modifier.FINAL);
188
189             /* valid HTTP methods */
190             String[] methods = {
191                        "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE", "PATCH"
192             };
193             // set the new methods - including patch
194             methodsField.set(null, methods);
195
196         } catch (SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException e) {
197                 LOG.warn("Adding PATCH method", e);
198         }
199         LOG.info("AAIResource.ctor initialized.");
200
201     }
202
203     private static final Logger LOG = LoggerFactory.getLogger(AAIService.class);
204     private final MetricLogger ml = new MetricLogger();
205
206     private SSLContext CTX;
207
208
209     private int connection_timeout = 300000;
210
211     private int read_timeout = 300000;
212
213     /**
214      * Returns an String that contains JSON data returned from the AAI Server.
215      * <p>
216      * This method always returns immediately, whether or not the
217      * data exists.
218      *
219      * @param  request  an instance of AAIRequiest representing
220      *                 the request made by DirectedGraph node.
221      * @return      the JSON based representation of data instance requested.
222      * @see         String
223      */
224     @Override
225     public String get(AAIRequest request) throws AAIServiceException {
226         String response = null;
227         InputStream inputStream = null;
228         HttpURLConnection con = null;
229         URL requestUrl = null;
230
231         StringBuilder errorStringBuilder = new StringBuilder();
232
233         try {
234
235             if(request.getRequestObject() != null) {
236                 requestUrl = request.getRequestUrl(HttpMethod.POST, null);
237                 requestUrl = appendDepth(requestUrl, request);
238                 con = getConfiguredConnection(requestUrl, HttpMethod.POST);
239                 String json_text = request.toJSONString();
240                 LOGwriteDateTrace("data", json_text);
241                 logMetricRequest("POST "+requestUrl.getPath(), json_text, requestUrl.getPath());
242                 OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
243                 osw.write(json_text);
244                 osw.flush();
245             } else {
246                 requestUrl = request.getRequestUrl(HttpMethod.GET, null);
247                 requestUrl = appendDepth(requestUrl, request);
248                 con = getConfiguredConnection(requestUrl, HttpMethod.GET);
249                 logMetricRequest("GET "+requestUrl.getPath(), "", requestUrl.getPath());
250             }
251
252             // Check for errors
253             String responseMessage = con.getResponseMessage();
254             int responseCode = con.getResponseCode();
255             if (responseCode == HttpURLConnection.HTTP_OK) {
256                 inputStream = con.getInputStream();
257             } else {
258                 inputStream = con.getErrorStream();
259             }
260
261             // Process the response
262             LOG.debug("HttpURLConnection result:" + responseCode + " : " + responseMessage);
263             logMetricResponse(responseCode, responseMessage);
264
265             if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
266             BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
267
268             ObjectMapper mapper = AAIService.getObjectMapper();
269
270             if (responseCode == HttpURLConnection.HTTP_OK) {
271                 StringBuilder stringBuilder = new StringBuilder();
272                 String line = null;
273                 while( ( line = reader.readLine() ) != null ) {
274                     stringBuilder.append( line );
275                 }
276                 response = stringBuilder.toString();
277                 try {
278                     Object object = mapper.readValue(response, Object.class);
279                     LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, responseMessage, mapper.writeValueAsString(object));
280                 } catch(Exception exc) {
281                     LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, responseMessage, mapper.writeValueAsString(response));
282                 }
283             } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
284                 LOGwriteEndingTrace(responseCode, responseMessage, "Entry does not exist.");
285                 ErrorResponse errorresponse = null;
286                 try {
287                     errorresponse = mapper.readValue(reader, ErrorResponse.class);
288                 } catch(Exception exc) {
289                     errorresponse = new ErrorResponse();
290                     RequestError requestError = new RequestError();
291                     ServiceException serviceException = new ServiceException();
292                     serviceException.setText("Entry does not exist.");
293                     requestError.setServiceException(serviceException);
294                     errorresponse.setRequestError(requestError );
295                 }
296                 throw new AAIServiceException(responseCode, errorresponse);
297             } else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
298                 StringBuilder stringBuilder = new StringBuilder();
299                 String line = null;
300                 while( ( line = reader.readLine() ) != null ) {
301                     stringBuilder.append( line );
302                 }
303                 LOGwriteEndingTrace(responseCode, responseMessage, stringBuilder.toString());
304                 ServiceException serviceException = new ServiceException();
305                 serviceException.setMessageId("HTTP_UNAUTHORIZED");
306                 serviceException.setText(stringBuilder.toString());
307                 RequestError requestError = new RequestError();
308                 requestError.setServiceException(serviceException);
309                 ErrorResponse errorresponse = new ErrorResponse();
310                 errorresponse.setRequestError(requestError);
311                 throw new AAIServiceException(responseCode, errorresponse);
312             } else {
313 //                StringBuilder errorStringBuilder = new StringBuilder();
314                 String line = null;
315                 while( ( line = reader.readLine() ) != null ) {
316                     errorStringBuilder.append("\n").append( line );
317                 }
318
319                 ErrorResponse errorresponse = mapper.readValue(errorStringBuilder.toString(), ErrorResponse.class);
320 //                ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
321                 LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
322                 throw new AAIServiceException(responseCode, errorresponse);
323             }
324
325         } catch(AAIServiceException aaiexc) {
326             throw aaiexc;
327         } catch (Exception exc) {
328             LOG.warn(errorStringBuilder.toString(), exc);
329             throw new AAIServiceException(exc);
330         } finally {
331             if(inputStream != null){
332                 try {
333                     inputStream.close();
334                 } catch(Exception exc) {
335
336                 }
337             }
338         }
339         return response;
340     }
341
342     /**
343      * Returns an String that contains JSON data returned from the AAI Server.
344      * <p>
345      * This method always returns immediately, whether or not the
346      * data exists.
347      *
348      * @param  request  an instance of AAIRequiest representing
349      *                 the request made by DirectedGraph node.
350      * @return      the JSON based representation of data instance requested.
351      * @see         String
352      */
353     @Override
354     public String post(AAIRequest request) throws AAIServiceException {
355         InputStream inputStream = null;
356
357         try {
358             String resourceVersion = null;
359             AAIDatum instance = request.getRequestObject();
360
361             try {
362                 Method getResourceVersionMethod = instance.getClass().getMethod("getResourceVersion");
363                 if(getResourceVersionMethod != null){
364                     try {
365                         Object object = getResourceVersionMethod.invoke(instance);
366                         if(object != null)
367                             resourceVersion = object.toString();
368                     } catch (InvocationTargetException x) {
369                         Throwable cause = x.getCause();
370                     }
371                 }
372             } catch(Exception exc) {
373                 LOG.error("", exc);
374             }
375
376             URL requestUrl = null;
377             HttpURLConnection con = getConfiguredConnection(requestUrl = request.getRequestUrl(HttpMethod.PUT, resourceVersion), HttpMethod.PUT);
378             ObjectMapper mapper = AAIService.getObjectMapper();
379             String json_text = request.toJSONString();
380
381             LOGwriteDateTrace("data", json_text);
382             logMetricRequest("PUT "+requestUrl.getPath(), json_text, requestUrl.getPath());
383
384             OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
385             osw.write(json_text);
386             osw.flush();
387
388             // Check for errors
389             String responseMessage = con.getResponseMessage();
390             int responseCode = con.getResponseCode();
391             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
392                 inputStream = con.getInputStream();
393             } else {
394                 inputStream = con.getErrorStream();
395             }
396
397             LOG.debug("HttpURLConnection result:" + responseCode + " : " + responseMessage);
398             logMetricResponse(responseCode, responseMessage);
399
400             // Process the response
401             BufferedReader reader;
402             String line = null;
403             reader = new BufferedReader( new InputStreamReader( inputStream ) );
404             mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
405
406             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
407                 StringBuilder stringBuilder = new StringBuilder();
408
409                 while( ( line = reader.readLine() ) != null ) {
410                     stringBuilder.append( line );
411                 }
412                 LOGwriteEndingTrace(responseCode, responseMessage, (stringBuilder.length() > 0) ? stringBuilder.toString() : "{no-data}");
413                 return stringBuilder.toString();
414             } else {
415                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
416                 LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
417
418                 throw new AAIServiceException(responseCode, errorresponse);
419             }
420         } catch(AAIServiceException aaiexc) {
421             throw aaiexc;
422         } catch (Exception exc) {
423             LOG.warn("AAIRequestExecutor.post", exc);
424             throw new AAIServiceException(exc);
425         } finally {
426             try {
427                 if(inputStream != null)
428                 inputStream.close();
429             } catch (Exception exc) {
430
431             }
432         }
433     }
434
435     /**
436      * Returns Boolean that contains completion state of the command executed.
437      * <p>
438      * This method always returns immediately, whether or not the
439      * data exists.
440      *
441      * @param  request  an instance of AAIRequiest representing
442      * @param  resourceVersion  a resource version of the data instacne to be deleted.
443      *                 the request made by DirectedGraph node.
444      * @return      completion state of the command.
445      * @see         String
446      */
447     @Override
448     public Boolean delete(AAIRequest request, String resourceVersion) throws AAIServiceException {
449         Boolean response = null;
450         InputStream inputStream = null;
451
452         if(resourceVersion == null) {
453             throw new AAIServiceException("resource-version is required for DELETE request");
454         }
455
456         try {
457             URL requestUrl = null;
458             HttpURLConnection conn = getConfiguredConnection(requestUrl = request.getRequestUrl(HttpMethod.DELETE, resourceVersion), HttpMethod.DELETE);
459             logMetricRequest("DELETE "+requestUrl.getPath(), "", requestUrl.getPath());
460             conn.setDoOutput(true);
461
462             // Check for errors
463             String responseMessage = conn.getResponseMessage();
464             int responseCode = conn.getResponseCode();
465             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
466                 inputStream = conn.getInputStream();
467             } else {
468                 inputStream = conn.getErrorStream();
469             }
470
471             // Process the response
472             LOG.debug("HttpURLConnection result:" + responseCode + " : " + responseMessage);
473             logMetricResponse(responseCode, responseMessage);
474
475             if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
476             BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
477             String line = null;
478
479             ObjectMapper mapper = AAIService.getObjectMapper();
480
481             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
482                 StringBuilder stringBuilder = new StringBuilder();
483
484                 while( ( line = reader.readLine() ) != null ) {
485                     stringBuilder.append( line );
486                 }
487                 LOGwriteEndingTrace(responseCode, responseMessage, stringBuilder.toString());
488                 response = true;
489             } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
490                 LOGwriteEndingTrace(responseCode, responseMessage, "Entry does not exist.");
491                 response = false;
492             } else {
493                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
494                 LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
495                 throw new AAIServiceException(responseCode, errorresponse);
496             }
497         } catch(AAIServiceException aaiexc) {
498             throw aaiexc;
499         } catch (Exception exc) {
500             LOG.warn("delete", exc);
501             throw new AAIServiceException(exc);
502         } finally {
503             if(inputStream != null){
504                 try {
505                     inputStream.close();
506                 } catch(Exception exc) {
507
508                 }
509             }
510         }
511         return response;
512     }
513
514     /**
515      * Returns an String that contains JSON data returned from the AAI Server.
516      * <p>
517      * This method always returns immediately, whether or not the
518      * data exists.
519      *
520      * @param  request  an instance of AAIRequiest representing
521      *                 the request made by DirectedGraph node.
522      * @param clas   an definition of the class for which data will be returned
523      * @return      the instance of the class with data.
524      * @see         String
525      */
526     @Override
527     public Object query(AAIRequest request, Class clas) throws AAIServiceException {
528         Object response = null;
529         InputStream inputStream = null;
530         HttpURLConnection con = null;
531         URL requestUrl = null;
532
533         try {
534             con = getConfiguredConnection(requestUrl = request.getRequestQueryUrl(HttpMethod.GET), HttpMethod.GET);
535             logMetricRequest("GET "+requestUrl.getPath(), "", requestUrl.getPath());
536
537             // Check for errors
538             String responseMessage = con.getResponseMessage();
539             int responseCode = con.getResponseCode();
540             if (responseCode == HttpURLConnection.HTTP_OK) {
541                 inputStream = con.getInputStream();
542             } else {
543                 inputStream = con.getErrorStream();
544             }
545
546             logMetricResponse(responseCode, responseMessage);
547             ObjectMapper mapper = AAIService.getObjectMapper();
548
549             if (responseCode == HttpURLConnection.HTTP_OK) {
550                 // Process the response
551                 BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
552                 response = mapper.readValue(reader, clas);
553                 LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, "SUCCESS", mapper.writeValueAsString(response));
554             } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
555                 LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
556                 return response;
557             } else {
558                 BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
559                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
560                 LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
561                 throw new AAIServiceException(responseCode, errorresponse);
562             }
563
564         } catch(AAIServiceException aaiexc) {
565             throw aaiexc;
566         } catch (Exception exc) {
567             LOG.warn("GET", exc);
568             throw new AAIServiceException(exc);
569         } finally {
570             if(inputStream != null){
571                 try {
572                     inputStream.close();
573                 } catch(Exception exc) {
574
575                 }
576             }
577             con = null;
578         }
579         return response;
580     }
581
582     @Override
583     public Boolean patch(AAIRequest request, String resourceVersion) throws AAIServiceException {
584         InputStream inputStream = null;
585
586         try {
587             AAIDatum instance = request.getRequestObject();
588             if(instance instanceof ResourceVersion) {
589                 resourceVersion = ((ResourceVersion)instance).getResourceVersion();
590             }
591
592             URL requestUrl = null;
593             HttpURLConnection con = getConfiguredConnection(requestUrl = request.getRequestUrl("PATCH", resourceVersion), "PATCH");
594             ObjectMapper mapper = AAIService.getObjectMapper();
595             String json_text = request.toJSONString();
596
597             LOGwriteDateTrace("data", json_text);
598             logMetricRequest("PATCH "+requestUrl.getPath(), json_text, requestUrl.getPath());
599
600             OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
601             osw.write(json_text);
602             osw.flush();
603
604             // Check for errors
605             String responseMessage = con.getResponseMessage();
606             int responseCode = con.getResponseCode();
607             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
608                 inputStream = con.getInputStream();
609             } else {
610                 inputStream = con.getErrorStream();
611             }
612
613             LOG.info("HttpURLConnection result: " + responseCode + " : " + responseMessage);
614             logMetricResponse(responseCode, responseMessage);
615
616             // Process the response
617             BufferedReader reader;
618             String line = null;
619             reader = new BufferedReader( new InputStreamReader( inputStream ) );
620             mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
621
622             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
623                 StringBuilder stringBuilder = new StringBuilder();
624
625                 while( ( line = reader.readLine() ) != null ) {
626                     stringBuilder.append( line );
627                 }
628                 LOGwriteEndingTrace(responseCode, responseMessage, (stringBuilder != null) ? stringBuilder.toString() : "{no-data}");
629                 return true;
630             } else {
631                 StringBuilder stringBuilder = new StringBuilder();
632
633                 while( ( line = reader.readLine() ) != null ) {
634                     stringBuilder.append("\n").append( line );
635                 }
636                 LOG.info(stringBuilder.toString());
637
638
639                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
640                 LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
641
642                 throw new AAIServiceException(responseCode, errorresponse);
643             }
644         } catch(AAIServiceException aaiexc) {
645             throw aaiexc;
646         } catch (Exception exc) {
647             LOG.warn("AAIRequestExecutor.patch", exc);
648             throw new AAIServiceException(exc);
649         } finally {
650             try {
651                 if(inputStream != null)
652                 inputStream.close();
653             } catch (Exception exc) {
654
655             }
656         }
657     }
658
659     /**
660      *
661      * @param httpReqUrl
662      * @param method
663      * @return
664      * @throws Exception
665      */
666     protected HttpURLConnection getConfiguredConnection(URL httpReqUrl, String method) throws Exception {
667         HttpURLConnection con = (HttpURLConnection) httpReqUrl.openConnection();
668
669         // Set up the connection properties
670         con.setRequestProperty("Connection", "close");
671         con.setDoInput(true);
672         con.setDoOutput(true);
673         con.setUseCaches(false);
674         con.setConnectTimeout(connection_timeout);
675         con.setReadTimeout(read_timeout);
676         con.setRequestMethod(method);
677         con.setRequestProperty("Accept", "application/json");
678         con.setRequestProperty("Transfer-Encoding","chunked");
679         con.setRequestProperty("Content-Type",
680                 "PATCH".equalsIgnoreCase(method) ? "application/merge-patch+json" : "application/json");
681         con.setRequestProperty("X-FromAppId", applicationId);
682         con.setRequestProperty("X-TransactionId", TransactionIdTracker.getNextTransactionId());
683         String mlId = ml.getRequestID();
684         if (mlId != null && !mlId.isEmpty()) {
685             LOG.debug(String.format("MetricLogger requestId = %s", mlId));
686             con.setRequestProperty(MetricLogger.REQUEST_ID, mlId);
687         } else {
688             LOG.debug("MetricLogger requestId is null");
689         }
690
691         if (userName != null && !userName.isEmpty() && userPassword != null && !userPassword.isEmpty()) {
692             String basicAuth = "Basic " + new String(Base64.encodeBase64((userName + ":" + userPassword).getBytes()));
693             con.setRequestProperty("Authorization", basicAuth);
694         }
695
696         if (con instanceof HttpsURLConnection && CTX != null) {
697             SSLSocketFactory sockFact = CTX.getSocketFactory();
698             HttpsURLConnection.class.cast(con).setSSLSocketFactory(sockFact);
699         }
700         return con;
701     }
702
703     private URL appendDepth(URL requestUrl, AAIRequest request) throws MalformedURLException {
704
705         String depth = request.requestProperties.getProperty("depth", "1");
706         String path = requestUrl.toString();
707         if(path.contains("?depth=") || path.contains("&depth=")) {
708             return requestUrl;
709         } else {
710             if(path.contains("?")) {
711                 path = String.format("%s&depth=%s", path, depth);
712             } else {
713                 path = String.format("%s?depth=%s", path, depth);
714             }
715             return new URL(path);
716         }
717     }
718
719     public void logMetricRequest(String targetServiceName, String msg, String path){
720         String svcInstanceId = "";
721         String svcName = null;
722         String partnerName = null;
723         String targetEntity = "A&AI";
724         String targetVirtualEntity = null;
725
726         targetServiceName = "";
727
728         ml.logRequest(svcInstanceId, svcName, partnerName, targetEntity, targetServiceName, targetVirtualEntity, msg);
729     }
730
731     public void logMetricResponse(int responseCode, String responseDescription){
732         ml.logResponse(responseCode < 400 ? "SUCCESS" : "FAILURE", Integer.toString(responseCode), responseDescription);
733     }
734
735     protected void LOGwriteFirstTrace(String method, String url) {
736         String time = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").format(System.currentTimeMillis());
737         LOG.info("A&AI transaction :");
738         LOG.info("Request Time : " + time + ", Method : " + method);
739         LOG.info("Request URL : "+ url);
740     }
741
742     protected void LOGwriteDateTrace(String name, String data) {
743         LOG.info("Input - " + name  + " : " + data);
744     }
745
746     protected void LOGwriteEndingTrace(int response_code, String comment, String data) {
747         LOG.info("Response code : " + response_code +", " + comment);
748         LOG.info(String.format("Response data : %s", data));
749     }
750
751 }