2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
 
   7  * ================================================================================
 
   8  * Modifications Copyright (C) 2018 IBM.
 
   9  * ================================================================================
 
  10  * Licensed under the Apache License, Version 2.0 (the "License");
 
  11  * you may not use this file except in compliance with the License.
 
  12  * You may obtain a copy of the License at
 
  14  *      http://www.apache.org/licenses/LICENSE-2.0
 
  16  * Unless required by applicable law or agreed to in writing, software
 
  17  * distributed under the License is distributed on an "AS IS" BASIS,
 
  18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  19  * See the License for the specific language governing permissions and
 
  20  * limitations under the License.
 
  21  * ============LICENSE_END=========================================================
 
  24 package org.onap.ccsdk.sli.adaptors.aai;
 
  26 import java.io.BufferedReader;
 
  27 import java.io.ByteArrayInputStream;
 
  29 import java.io.FileInputStream;
 
  30 import java.io.InputStream;
 
  31 import java.io.InputStreamReader;
 
  32 import java.io.OutputStreamWriter;
 
  33 import java.lang.reflect.Field;
 
  34 import java.lang.reflect.InvocationTargetException;
 
  35 import java.lang.reflect.Method;
 
  36 import java.lang.reflect.Modifier;
 
  37 import java.net.HttpURLConnection;
 
  38 import java.net.MalformedURLException;
 
  39 import java.net.URISyntaxException;
 
  41 import java.nio.charset.StandardCharsets;
 
  42 import java.security.KeyManagementException;
 
  43 import java.security.KeyStore;
 
  44 import java.security.NoSuchAlgorithmException;
 
  45 import java.text.SimpleDateFormat;
 
  46 import java.util.Properties;
 
  48 import javax.net.ssl.HttpsURLConnection;
 
  49 import javax.net.ssl.KeyManagerFactory;
 
  50 import javax.net.ssl.SSLContext;
 
  51 import javax.net.ssl.SSLSession;
 
  52 import javax.net.ssl.SSLSocketFactory;
 
  54 import org.apache.commons.codec.binary.Base64;
 
  55 import org.apache.commons.lang3.ObjectUtils;
 
  56 import org.onap.ccsdk.sli.adaptors.aai.AAIService.TransactionIdTracker;
 
  57 import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
 
  58 import org.onap.ccsdk.sli.adaptors.aai.data.ErrorResponse;
 
  59 import org.onap.ccsdk.sli.adaptors.aai.data.RequestError;
 
  60 import org.onap.ccsdk.sli.adaptors.aai.data.ResourceVersion;
 
  61 import org.onap.ccsdk.sli.adaptors.aai.data.ServiceException;
 
  62 import org.onap.ccsdk.sli.adaptors.aai.update.BulkUpdateResponseData;
 
  63 import org.onap.ccsdk.sli.core.sli.MetricLogger;
 
  64 import org.onap.logging.ref.slf4j.ONAPLogConstants;
 
  65 import org.slf4j.Logger;
 
  66 import org.slf4j.LoggerFactory;
 
  68 import com.fasterxml.jackson.databind.DeserializationFeature;
 
  69 import com.fasterxml.jackson.databind.ObjectMapper;
 
  71 import org.apache.http.client.utils.URIBuilder;
 
  72 import org.apache.http.impl.EnglishReasonPhraseCatalog;
 
  75  * The AAIClientRESTExecutor class provides CRUD API for AAI Client service.
 
  76  * @author  Rich Tabedzki
 
  78 public class AAIClientRESTExecutor implements AAIExecutorInterface {
 
  80     private final String truststorePath;
 
  81     private final String truststorePassword;
 
  82     private final String keystorePath;
 
  83     private final String keystorePassword;
 
  84     private final Boolean ignoreCertificateHostError;
 
  85     // authentication credentials
 
  86     private String userName;
 
  87     private String userPassword;
 
  88     private final String applicationId;
 
  89     private static final String HTTP_URL_CONNECTION_RESULT="HttpURLConnection result: {} : {}";
 
  90     private static final String ENTRY_DOESNT_EXIST="Entry does not exist.";
 
  94      * @param props - properties to initialize an instance.
 
  96     public AAIClientRESTExecutor(Properties props) {
 
  99         userName            = props.getProperty(AAIService.CLIENT_NAME);
 
 100         userPassword        = props.getProperty(AAIService.CLIENT_PWWD);
 
 102         if(userName == null || userName.isEmpty()){
 
 103             LOG.debug("Basic user name is not set");
 
 105         if(userPassword == null || userPassword.isEmpty()) {
 
 106             LOG.debug("Basic password is not set");
 
 109         truststorePath     = props.getProperty(AAIService.TRUSTSTORE_PATH);
 
 110         truststorePassword = props.getProperty(AAIService.TRUSTSTORE_PSSWD);
 
 111         keystorePath         = props.getProperty(AAIService.KEYSTORE_PATH);
 
 112         keystorePassword     = props.getProperty(AAIService.KEYSTORE_PSSWD);
 
 114         String tmpApplicationId =props.getProperty(AAIService.APPLICATION_ID);
 
 115         if(tmpApplicationId == null || tmpApplicationId.isEmpty()) {
 
 116             tmpApplicationId = "SDNC";
 
 118         applicationId = tmpApplicationId;
 
 120         String iche = props.getProperty(AAIService.CERTIFICATE_HOST_ERROR);
 
 121         boolean host_error = false;
 
 122         if(iche != null && !iche.isEmpty()) {
 
 123             host_error = Boolean.valueOf(iche);
 
 126         ignoreCertificateHostError = host_error;
 
 128         HttpsURLConnection.setDefaultHostnameVerifier( (String string,SSLSession ssls)  -> {
 
 129              return ignoreCertificateHostError;
 
 133         if(truststorePath != null && truststorePassword != null && (new File(truststorePath)).exists()) {
 
 134             System.setProperty("javax.net.ssl.trustStore", truststorePath);
 
 135             System.setProperty("javax.net.ssl.trustStorePassword", truststorePassword);
 
 138         if(keystorePath != null && keystorePassword != null && (new File(keystorePath)).exists())
 
 140             //both jersey and HttpURLConnection can use this
 
 141             SSLContext ctx = null;
 
 143                 ctx = SSLContext.getInstance("TLS");
 
 145                 KeyManagerFactory kmf = null;
 
 146                 try (FileInputStream fin = new FileInputStream(keystorePath)){
 
 147                     String storeType = "PKCS12";
 
 148                     String def = KeyStore.getDefaultType();
 
 149                     kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
 
 151                     String extension = keystorePath.substring(keystorePath.lastIndexOf(".") + 1);
 
 153                     if(extension != null && !extension.isEmpty() && "JKS".equalsIgnoreCase(extension)) {
 
 156                     KeyStore ks = KeyStore.getInstance(storeType);
 
 158                     char[] pwd = keystorePassword.toCharArray();
 
 161                 } catch (Exception ex) {
 
 162                     LOG.error("AAIResource", ex);
 
 164                 if (ObjectUtils.anyNotNull(kmf)) {
 
 165                     ctx.init(kmf.getKeyManagers(), null, null);
 
 169                 LOG.debug("SSLContext created");
 
 171             } catch (KeyManagementException | NoSuchAlgorithmException exc) {
 
 172                 LOG.error("AAIResource", exc);
 
 177             Field methodsField = HttpURLConnection.class.getDeclaredField("methods");
 
 178             methodsField.setAccessible(true);
 
 179             // get the methods field modifiers
 
 180             Field modifiersField = Field.class.getDeclaredField("modifiers");
 
 181             // bypass the "private" modifier
 
 182             modifiersField.setAccessible(true);
 
 184             // remove the "final" modifier
 
 185             modifiersField.setInt(methodsField, methodsField.getModifiers() & ~Modifier.FINAL);
 
 187             /* valid HTTP methods */
 
 189                        "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE", "PATCH"
 
 191             // set the new methods - including patch
 
 192             methodsField.set(null, methods);
 
 194         } catch (SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException e) {
 
 195             LOG.warn("Adding PATCH method", e);
 
 197         LOG.info("AAIResource.ctor initialized.");
 
 201     private static final Logger LOG = LoggerFactory.getLogger(AAIService.class);
 
 202     private static final String NOT_PROVIDED = "NOT PROVIDED";
 
 203     private final MetricLogger ml = new MetricLogger();
 
 205     private SSLContext CTX;
 
 208     private int connection_timeout = 300000;
 
 210     private int read_timeout = 300000;
 
 213      * Returns an String that contains JSON data returned from the AAI Server.
 
 215      * This method always returns immediately, whether or not the
 
 218      * @param  request  an instance of AAIRequiest representing
 
 219      *                 the request made by DirectedGraph node.
 
 220      * @return      the JSON based representation of data instance requested.
 
 224     public String get(AAIRequest request) throws AAIServiceException {
 
 225         String response = null;
 
 226         InputStream inputStream = null;
 
 227         HttpURLConnection con = null;
 
 228         URL requestUrl = null;
 
 230         StringBuilder errorStringBuilder = new StringBuilder();
 
 234             if(request.getRequestObject() != null) {
 
 235                 requestUrl = request.getRequestUrl(HttpMethod.POST, null);
 
 236                 requestUrl = appendDepth(requestUrl, request);
 
 237                 LOG.info(String.format("%s : %s", HttpMethod.GET, requestUrl.toString()));
 
 238                 con = getConfiguredConnection(requestUrl, HttpMethod.POST);
 
 239                 String json_text = request.toJSONString();
 
 240                 LOGwriteDateTrace("data", json_text);
 
 241                 logMetricRequest("POST "+requestUrl.toString(), json_text, requestUrl.toString());
 
 242                 OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
 
 243                 osw.write(json_text);
 
 246                 requestUrl = request.getRequestUrl(HttpMethod.GET, null);
 
 247                 requestUrl = appendDepth(requestUrl, request);
 
 248                 LOG.info(String.format("%s : %s", HttpMethod.GET, requestUrl.toString()));
 
 249                 con = getConfiguredConnection(requestUrl, HttpMethod.GET);
 
 250                 logMetricRequest("GET "+requestUrl.toString(), "", requestUrl.toString());
 
 254             int responseCode = con.getResponseCode();
 
 255             if (responseCode == HttpURLConnection.HTTP_OK) {
 
 256                 inputStream = con.getInputStream();
 
 258                 inputStream = con.getErrorStream();
 
 260             String responseMessage = null;
 
 262                 responseMessage = con.getResponseMessage();
 
 263             } catch(Exception exc) {
 
 264                 responseMessage = EnglishReasonPhraseCatalog.INSTANCE.getReason(responseCode,null);
 
 266                 if(responseMessage == null)
 
 267                         responseMessage = NOT_PROVIDED;
 
 270             // Process the response
 
 271             LOG.info(HTTP_URL_CONNECTION_RESULT, responseCode, responseMessage);
 
 272             logMetricResponse(responseCode, responseMessage);
 
 274             if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
 
 275             BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
 
 277             ObjectMapper mapper = AAIService.getObjectMapper();
 
 279             if (responseCode == HttpURLConnection.HTTP_OK) {
 
 280                 StringBuilder stringBuilder = new StringBuilder();
 
 282                 while( ( line = reader.readLine() ) != null ) {
 
 283                     stringBuilder.append( line );
 
 285                 response = stringBuilder.toString();
 
 287                     Object object = mapper.readValue(response, Object.class);
 
 288                     LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, responseMessage, mapper.writeValueAsString(object));
 
 289                 } catch(Exception exc) {
 
 290                     LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, responseMessage, mapper.writeValueAsString(response));
 
 292             } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
 
 293                 LOGwriteEndingTrace(responseCode, responseMessage, ENTRY_DOESNT_EXIST);
 
 294                 ErrorResponse errorresponse = null;
 
 296                     errorresponse = mapper.readValue(reader, ErrorResponse.class);
 
 297                 } catch(Exception exc) {
 
 298                     errorresponse = new ErrorResponse();
 
 299                     RequestError requestError = new RequestError();
 
 300                     ServiceException serviceException = new ServiceException();
 
 301                     serviceException.setText(ENTRY_DOESNT_EXIST);
 
 302                     requestError.setServiceException(serviceException);
 
 303                     errorresponse.setRequestError(requestError );
 
 305                 throw new AAIServiceException(responseCode, errorresponse);
 
 306             } else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
 
 307                 StringBuilder stringBuilder = new StringBuilder();
 
 309                 while( ( line = reader.readLine() ) != null ) {
 
 310                     stringBuilder.append( line );
 
 312                 LOGwriteEndingTrace(responseCode, responseMessage, stringBuilder.toString());
 
 313                 ServiceException serviceException = new ServiceException();
 
 314                 serviceException.setMessageId("HTTP_UNAUTHORIZED");
 
 315                 serviceException.setText(stringBuilder.toString());
 
 316                 RequestError requestError = new RequestError();
 
 317                 requestError.setServiceException(serviceException);
 
 318                 ErrorResponse errorresponse = new ErrorResponse();
 
 319                 errorresponse.setRequestError(requestError);
 
 320                 throw new AAIServiceException(responseCode, errorresponse);
 
 323                 while( ( line = reader.readLine() ) != null ) {
 
 324                     errorStringBuilder.append("\n").append( line );
 
 327                 ErrorResponse errorresponse = mapper.readValue(errorStringBuilder.toString(), ErrorResponse.class);
 
 328                 LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
 
 329                 throw new AAIServiceException(responseCode, errorresponse);
 
 332         } catch(AAIServiceException aaiexc) {
 
 334         } catch (Exception exc) {
 
 335             LOG.warn(errorStringBuilder.toString(), exc);
 
 336             throw new AAIServiceException(exc);
 
 338             if(inputStream != null){
 
 341                 } catch(Exception exc) {
 
 350      * Returns an String that contains JSON data returned from the AAI Server.
 
 352      * This method always returns immediately, whether or not the
 
 355      * @param  request  an instance of AAIRequiest representing
 
 356      *                 the request made by DirectedGraph node.
 
 357      * @return      the JSON based representation of data instance requested.
 
 361     public String post(AAIRequest request) throws AAIServiceException {
 
 362         InputStream inputStream = null;
 
 365             String resourceVersion = null;
 
 366             AAIDatum instance = request.getRequestObject();
 
 369                 Method getResourceVersionMethod = instance.getClass().getMethod("getResourceVersion");
 
 370                 if(getResourceVersionMethod != null){
 
 372                         Object object = getResourceVersionMethod.invoke(instance);
 
 374                             resourceVersion = object.toString();
 
 375                     } catch (InvocationTargetException exc) {
 
 379             } catch(Exception exc) {
 
 383             URL requestUrl = request.getRequestUrl(HttpMethod.PUT, resourceVersion);
 
 384             HttpURLConnection con = getConfiguredConnection(requestUrl, HttpMethod.PUT);
 
 385             String jsonText = request.toJSONString();
 
 386             LOGwriteDateTrace("data", jsonText);
 
 389                     OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
 
 394             logMetricRequest("PUT "+requestUrl.toString(), jsonText, requestUrl.toString());
 
 398             int responseCode = con.getResponseCode();
 
 399             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
 
 400                 inputStream = con.getInputStream();
 
 402                 inputStream = con.getErrorStream();
 
 404             String responseMessage = null;
 
 406                 responseMessage = con.getResponseMessage();
 
 407             } catch(Exception exc) {
 
 408                 responseMessage = EnglishReasonPhraseCatalog.INSTANCE.getReason(responseCode,null);
 
 410                 if(responseMessage == null)
 
 411                         responseMessage = NOT_PROVIDED;
 
 414             LOG.info(HTTP_URL_CONNECTION_RESULT, responseCode, responseMessage);
 
 415             logMetricResponse(responseCode, responseMessage);
 
 417             // Process the response
 
 418             ObjectMapper mapper = AAIService.getObjectMapper();
 
 419             BufferedReader reader;
 
 421             reader = new BufferedReader( new InputStreamReader( inputStream ) );
 
 422             mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
 
 424             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
 
 425                 StringBuilder stringBuilder = new StringBuilder();
 
 427                 while( ( line = reader.readLine() ) != null ) {
 
 428                     stringBuilder.append( line );
 
 430                 LOGwriteEndingTrace(responseCode, responseMessage, (stringBuilder.length() > 0) ? stringBuilder.toString() : "{no-data}");
 
 431                 return stringBuilder.toString();
 
 433                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
 
 434                 LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
 
 436                 throw new AAIServiceException(responseCode, errorresponse);
 
 438         } catch(AAIServiceException aaiexc) {
 
 440         } catch (Exception exc) {
 
 441             LOG.warn("AAIRequestExecutor.post", exc);
 
 442             throw new AAIServiceException(exc);
 
 445                 if(inputStream != null)
 
 447             } catch (Exception exc) {
 
 448                 LOG.warn("AAIRequestExecutor.post", exc);
 
 454      * Returns Boolean that contains completion state of the command executed.
 
 456      * This method always returns immediately, whether or not the
 
 459      * @param  request  an instance of AAIRequiest representing
 
 460      * @param  resourceVersion  a resource version of the data instacne to be deleted.
 
 461      *                 the request made by DirectedGraph node.
 
 462      * @return      completion state of the command.
 
 466     public Boolean delete(AAIRequest request, String resourceVersion) throws AAIServiceException {
 
 467         Boolean response = null;
 
 468         InputStream inputStream = null;
 
 470         if(resourceVersion == null) {
 
 471             throw new AAIServiceException("resource-version is required for DELETE request");
 
 475             URL requestUrl = request.getRequestUrl(HttpMethod.DELETE, resourceVersion);
 
 476             HttpURLConnection conn = getConfiguredConnection(requestUrl, HttpMethod.DELETE);
 
 477             logMetricRequest("DELETE "+requestUrl.getPath(), "", requestUrl.getPath());
 
 478             conn.setDoOutput(true);
 
 481             int responseCode = conn.getResponseCode();
 
 482             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
 
 483                 inputStream = conn.getInputStream();
 
 485                 inputStream = conn.getErrorStream();
 
 487             String responseMessage = null;
 
 489                 responseMessage = conn.getResponseMessage();
 
 490             } catch(Exception exc) {
 
 491                 responseMessage = EnglishReasonPhraseCatalog.INSTANCE.getReason(responseCode,null);
 
 493                 if(responseMessage == null)
 
 494                         responseMessage = NOT_PROVIDED;
 
 497             // Process the response
 
 498             LOG.info(HTTP_URL_CONNECTION_RESULT, responseCode, responseMessage);
 
 499             logMetricResponse(responseCode, responseMessage);
 
 501             if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
 
 502             BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
 
 505             ObjectMapper mapper = AAIService.getObjectMapper();
 
 507             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
 
 508                 StringBuilder stringBuilder = new StringBuilder();
 
 510                 while( ( line = reader.readLine() ) != null ) {
 
 511                     stringBuilder.append( line );
 
 513                 LOGwriteEndingTrace(responseCode, responseMessage, stringBuilder.toString());
 
 515             } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
 
 516                 LOGwriteEndingTrace(responseCode, responseMessage, ENTRY_DOESNT_EXIST);
 
 519                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
 
 520                 LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
 
 521                 throw new AAIServiceException(responseCode, errorresponse);
 
 523         } catch(AAIServiceException aaiexc) {
 
 525         } catch (Exception exc) {
 
 526             LOG.warn("delete", exc);
 
 527             throw new AAIServiceException(exc);
 
 529             if(inputStream != null){
 
 532                 } catch(Exception exc) {
 
 533                     LOG.warn("delete", exc);
 
 541      * Returns an String that contains JSON data returned from the AAI Server.
 
 543      * This method always returns immediately, whether or not the
 
 546      * @param  request  an instance of AAIRequiest representing
 
 547      *                 the request made by DirectedGraph node.
 
 548      * @param clas   an definition of the class for which data will be returned
 
 549      * @return      the instance of the class with data.
 
 553     public Object query(AAIRequest request, Class clas) throws AAIServiceException {
 
 554         Object response = null;
 
 555         InputStream inputStream = null;
 
 558             URL requestUrl = request.getRequestQueryUrl(HttpMethod.GET);
 
 559             HttpURLConnection con = getConfiguredConnection(requestUrl, HttpMethod.GET);
 
 560             logMetricRequest("GET "+requestUrl.getPath(), "", requestUrl.getPath());
 
 563             int responseCode = con.getResponseCode();
 
 564             if (responseCode == HttpURLConnection.HTTP_OK) {
 
 565                 inputStream = con.getInputStream();
 
 567                 inputStream = con.getErrorStream();
 
 569             String responseMessage = null;
 
 571                 responseMessage = con.getResponseMessage();
 
 572             } catch(Exception exc) {
 
 573                 responseMessage = EnglishReasonPhraseCatalog.INSTANCE.getReason(responseCode,null);
 
 575                 if(responseMessage == null)
 
 576                         responseMessage = NOT_PROVIDED;
 
 579             LOG.info(HTTP_URL_CONNECTION_RESULT, responseCode, responseMessage);
 
 580             logMetricResponse(responseCode, responseMessage);
 
 581             ObjectMapper mapper = AAIService.getObjectMapper();
 
 583             if (responseCode == HttpURLConnection.HTTP_OK) {
 
 584                 // Process the response
 
 585                 BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
 
 586                 response = mapper.readValue(reader, clas);
 
 587                 LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, "SUCCESS", mapper.writeValueAsString(response));
 
 588             } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
 
 589                 LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", ENTRY_DOESNT_EXIST);
 
 592                 BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
 
 593                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
 
 594                 LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
 
 595                 throw new AAIServiceException(responseCode, errorresponse);
 
 598         } catch(AAIServiceException aaiexc) {
 
 600         } catch (Exception exc) {
 
 601             LOG.warn("GET", exc);
 
 602             throw new AAIServiceException(exc);
 
 604             if(inputStream != null){
 
 607                 } catch(Exception exc) {
 
 608                     LOG.warn("GET", exc);
 
 616     public Boolean patch(AAIRequest request, String resourceVersion) throws AAIServiceException {
 
 617         InputStream inputStream = null;
 
 620             AAIDatum instance = request.getRequestObject();
 
 621             if(instance instanceof ResourceVersion) {
 
 622                 resourceVersion = ((ResourceVersion)instance).getResourceVersion();
 
 625             URL requestUrl = null;
 
 626             requestUrl = request.getRequestUrl("PATCH", resourceVersion);
 
 627             HttpURLConnection con = getConfiguredConnection(requestUrl, "PATCH");
 
 628             ObjectMapper mapper = AAIService.getObjectMapper();
 
 629             String jsonText = request.toJSONString();
 
 631             LOGwriteDateTrace("data", jsonText);
 
 632             logMetricRequest("PATCH "+requestUrl.getPath(), jsonText, requestUrl.getPath());
 
 634             OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
 
 639             int responseCode = con.getResponseCode();
 
 640             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
 
 641                 inputStream = con.getInputStream();
 
 643                 inputStream = con.getErrorStream();
 
 645             String responseMessage = null;
 
 647                 responseMessage = con.getResponseMessage();
 
 648             } catch(Exception exc) {
 
 649                 LOG.info("Exception occured", exc.getMessage());
 
 650                 responseMessage = EnglishReasonPhraseCatalog.INSTANCE.getReason(responseCode,null);
 
 652                 if(responseMessage == null)
 
 653                         responseMessage = NOT_PROVIDED;
 
 656             LOG.info(HTTP_URL_CONNECTION_RESULT, responseCode, responseMessage);
 
 657             logMetricResponse(responseCode, responseMessage);
 
 659             // Process the response
 
 660             BufferedReader reader;
 
 662             reader = new BufferedReader( new InputStreamReader( inputStream ) );
 
 663             mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
 
 665             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
 
 666                 StringBuilder stringBuilder = new StringBuilder();
 
 668                 while( ( line = reader.readLine() ) != null ) {
 
 669                     stringBuilder.append( line );
 
 671                 LOGwriteEndingTrace(responseCode, responseMessage, (stringBuilder.length() > 0) ? stringBuilder.toString() : "{no-data}");
 
 674                 StringBuilder stringBuilder = new StringBuilder();
 
 676                 while( ( line = reader.readLine() ) != null ) {
 
 677                     stringBuilder.append("\n").append( line );
 
 679                 LOG.info(stringBuilder.toString());
 
 682                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
 
 683                 LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
 
 685                 throw new AAIServiceException(responseCode, errorresponse);
 
 687         } catch(AAIServiceException aaiexc) {
 
 689         } catch (Exception exc) {
 
 690             LOG.warn("AAIRequestExecutor.patch", exc);
 
 691             throw new AAIServiceException(exc);
 
 694                 if(inputStream != null)
 
 696             } catch (Exception exc) {
 
 697                 LOG.warn("AAIRequestExecutor.patch", exc);
 
 703      * Returns an String that contains JSON data returned from the AAI Server.
 
 705      * This method always returns immediately, whether or not the
 
 708      * @param  request  an instance of AAIRequiest representing
 
 709      *                 the request made by DirectedGraph node.
 
 710      * @return      the JSON based representation of data instance requested.
 
 714     public String bulkUpdate(BulkUpdateRequest request) throws AAIServiceException {
 
 715         InputStream inputStream = null;
 
 718             URL requestUrl = request.getRequestUrl(HttpMethod.POST, null);
 
 719             HttpURLConnection con = getConfiguredConnection(requestUrl, HttpMethod.POST);
 
 720             String jsonText = request.toJSONString();
 
 721             LOGwriteDateTrace("data", jsonText);
 
 724                     OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
 
 729             logMetricRequest("POST "+requestUrl.toString(), jsonText, requestUrl.toString());
 
 733             int responseCode = con.getResponseCode();
 
 734             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
 
 735                 inputStream = con.getInputStream();
 
 737                 inputStream = con.getErrorStream();
 
 739             String responseMessage = null;
 
 741                 responseMessage = con.getResponseMessage();
 
 742             } catch(Exception exc) {
 
 743                 responseMessage = EnglishReasonPhraseCatalog.INSTANCE.getReason(responseCode,null);
 
 745                 if(responseMessage == null)
 
 746                         responseMessage = NOT_PROVIDED;
 
 749             LOG.info(HTTP_URL_CONNECTION_RESULT, responseCode, responseMessage);
 
 750             logMetricResponse(responseCode, responseMessage);
 
 752             // Process the response
 
 753             ObjectMapper mapper = AAIService.getObjectMapper();
 
 754             BufferedReader reader;
 
 756             reader = new BufferedReader( new InputStreamReader( inputStream ) );
 
 757             mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
 
 759             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
 
 760                 StringBuilder stringBuilder = new StringBuilder();
 
 762                 while( ( line = reader.readLine() ) != null ) {
 
 763                     stringBuilder.append( line );
 
 765                 LOGwriteEndingTrace(responseCode, responseMessage, (stringBuilder.length() > 0) ? stringBuilder.toString() : "{no-data}");
 
 766                 return stringBuilder.toString();
 
 768                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
 
 769                 LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
 
 771                 throw new AAIServiceException(responseCode, errorresponse);
 
 773         } catch(AAIServiceException aaiexc) {
 
 775         } catch (Exception exc) {
 
 776             LOG.warn("AAIRequestExecutor.post", exc);
 
 777             throw new AAIServiceException(exc);
 
 780                 if(inputStream != null)
 
 782             } catch (Exception exc) {
 
 783                 LOG.warn("AAIRequestExecutor.post", exc);
 
 795     protected HttpURLConnection getConfiguredConnection(URL httpReqUrl, String method) throws Exception {
 
 796         HttpURLConnection con = (HttpURLConnection) httpReqUrl.openConnection();
 
 798         // Set up the connection properties
 
 799         con.setRequestProperty("Connection", "close");
 
 800         con.setDoInput(true);
 
 801         con.setDoOutput(true);
 
 802         con.setUseCaches(false);
 
 803         con.setConnectTimeout(connection_timeout);
 
 804         con.setReadTimeout(read_timeout);
 
 805         con.setRequestMethod(method);
 
 806         con.setRequestProperty("Accept", "application/json");
 
 807         con.setRequestProperty("Transfer-Encoding","chunked");
 
 808         con.setRequestProperty("Content-Type",
 
 809                 "PATCH".equalsIgnoreCase(method) ? "application/merge-patch+json" : "application/json");
 
 810         con.setRequestProperty("X-FromAppId", applicationId);
 
 811         con.setRequestProperty("X-TransactionId", TransactionIdTracker.getNextTransactionId());
 
 812         con.setRequestProperty("X-DslApiVersion", "V2");
 
 813         String mlId = ml.getRequestID();
 
 814         if (mlId != null && !mlId.isEmpty()) {
 
 815             LOG.debug(String.format("MetricLogger requestId = %s", mlId));
 
 816             con.setRequestProperty(ONAPLogConstants.MDCs.REQUEST_ID, mlId);
 
 818             LOG.debug("MetricLogger requestId is null");
 
 821         if (userName != null && !userName.isEmpty() && userPassword != null && !userPassword.isEmpty()) {
 
 822             String basicAuth = "Basic " + new String(Base64.encodeBase64((userName + ":" + userPassword).getBytes()));
 
 823             con.setRequestProperty("Authorization", basicAuth);
 
 826         if (con instanceof HttpsURLConnection && CTX != null) {
 
 827             SSLSocketFactory sockFact = CTX.getSocketFactory();
 
 828             HttpsURLConnection.class.cast(con).setSSLSocketFactory(sockFact);
 
 833     private URL appendDepth(URL requestUrl, AAIRequest request) throws MalformedURLException, URISyntaxException {
 
 834         final String NODES_ONLY = "nodes-only";
 
 835         URIBuilder builder = new URIBuilder(requestUrl.toURI());
 
 836         // PROCESS nodes-only option
 
 837         if (request.requestProperties.containsKey(NODES_ONLY)) {
 
 838             if(request.requestProperties.containsKey(NODES_ONLY)) {
 
 839                 String nodesOnly = request.requestProperties.getProperty(NODES_ONLY);
 
 840                 if(nodesOnly != null && !nodesOnly.isEmpty()) {
 
 841                     builder.setParameter(NODES_ONLY, nodesOnly);
 
 844             // do not add depth by default with nodes-only
 
 845             if(!request.requestProperties.containsKey("depth")) {
 
 846                 return builder.build().toURL();
 
 850         String depth = request.requestProperties.getProperty("depth", "1");
 
 852         builder.setParameter("depth", depth);
 
 854         return builder.build().toURL();
 
 857     public void logMetricRequest(String targetServiceName, String msg, String path){
 
 858         String svcInstanceId = "";
 
 859         String svcName = null;
 
 860         String partnerName = null;
 
 861         String targetEntity = "A&AI";
 
 862         String targetVirtualEntity = null;
 
 864         ml.logRequest(svcInstanceId, svcName, partnerName, targetEntity, targetServiceName, targetVirtualEntity, msg);
 
 867     public void logMetricResponse(int responseCode, String responseDescription){
 
 868         ml.logResponse(responseCode < 400 ? "COMPLETE" : "ERROR", Integer.toString(responseCode), responseDescription);
 
 871     protected void LOGwriteFirstTrace(String method, String url) {
 
 872         String time = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").format(System.currentTimeMillis());
 
 873         LOG.info("A&AI transaction :");
 
 874         LOG.info("Request Time : " + time + ", Method : " + method);
 
 875         LOG.info("Request URL : "+ url);
 
 878     protected void LOGwriteDateTrace(String name, String data) {
 
 879         LOG.info("Input - " + name  + " : " + data);
 
 882     protected void LOGwriteEndingTrace(int response_code, String comment, String data) {
 
 883         LOG.info("Response code : " + response_code +", " + comment);
 
 884         LOG.info(String.format("Response data : %s", data));