Allow handling of legact model artifacts
[aai/model-loader.git] / src / main / java / org / openecomp / modelloader / restclient / AaiRestClient.java
index d4ee738..4d5e487 100644 (file)
-/**\r
- * ============LICENSE_START=======================================================\r
- * Model Loader\r
- * ================================================================================\r
- * Copyright © 2017 AT&T Intellectual Property.\r
- * Copyright © 2017 Amdocs\r
- * All rights reserved.\r
- * ================================================================================\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ============LICENSE_END=========================================================\r
- *\r
- * ECOMP and OpenECOMP are trademarks\r
- * and service marks of AT&T Intellectual Property.\r
- */\r
-package org.openecomp.modelloader.restclient;\r
-\r
-import com.sun.jersey.api.client.Client;\r
-import com.sun.jersey.api.client.ClientResponse;\r
-import com.sun.jersey.api.client.config.ClientConfig;\r
-import com.sun.jersey.api.client.config.DefaultClientConfig;\r
-import com.sun.jersey.api.client.filter.LoggingFilter;\r
-import com.sun.jersey.client.urlconnection.HTTPSProperties;\r
-import org.openecomp.cl.api.LogFields;\r
-import org.openecomp.cl.api.LogLine;\r
-import org.openecomp.cl.api.Logger;\r
-import org.openecomp.cl.eelf.LoggerFactory;\r
-import org.openecomp.cl.mdc.MdcContext;\r
-import org.openecomp.cl.mdc.MdcOverride;\r
-import org.openecomp.modelloader.config.ModelLoaderConfig;\r
-import org.openecomp.modelloader.service.ModelLoaderMsgs;\r
-import org.w3c.dom.Document;\r
-import org.w3c.dom.Node;\r
-import org.w3c.dom.NodeList;\r
-import org.xml.sax.InputSource;\r
-import org.xml.sax.SAXException;\r
-\r
-import java.io.ByteArrayOutputStream;\r
-import java.io.FileInputStream;\r
-import java.io.IOException;\r
-import java.io.PrintStream;\r
-import java.io.StringReader;\r
-import java.security.GeneralSecurityException;\r
-import java.security.KeyStore;\r
-import java.security.cert.X509Certificate;\r
-import java.text.SimpleDateFormat;\r
-\r
-import javax.net.ssl.HostnameVerifier;\r
-import javax.net.ssl.HttpsURLConnection;\r
-import javax.net.ssl.KeyManagerFactory;\r
-import javax.net.ssl.SSLContext;\r
-import javax.net.ssl.SSLSession;\r
-import javax.net.ssl.TrustManager;\r
-import javax.net.ssl.X509TrustManager;\r
-import javax.ws.rs.core.Response;\r
-import javax.xml.parsers.DocumentBuilder;\r
-import javax.xml.parsers.DocumentBuilderFactory;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-\r
-public class AaiRestClient {\r
-  public enum MimeType {\r
-    XML("application/xml"), JSON("application/json");\r
-\r
-    private String httpType;\r
-\r
-    MimeType(String httpType) {\r
-      this.httpType = httpType;\r
-    }\r
-\r
-    String getHttpHeaderType() {\r
-      return httpType;\r
-    }\r
-  }\r
-\r
-  private static String HEADER_TRANS_ID = "X-TransactionId";\r
-  private static String HEADER_FROM_APP_ID = "X-FromAppId";\r
-  private static String HEADER_AUTHORIZATION = "Authorization";\r
-  private static String ML_APP_NAME = "ModelLoader";\r
-  private static String RESOURCE_VERSION_PARAM = "resource-version";\r
-\r
-  private static SimpleDateFormat dateFormatter = new SimpleDateFormat(\r
-      "yyyy-MM-dd'T'HH:mm:ss.SSSXXX");\r
-\r
-  private static Logger logger = LoggerFactory.getInstance()\r
-      .getLogger(AaiRestClient.class.getName());\r
-  private static Logger metricsLogger = LoggerFactory.getInstance()\r
-      .getMetricsLogger(AaiRestClient.class.getName());\r
-\r
-  private ModelLoaderConfig config = null;\r
-\r
-  public AaiRestClient(ModelLoaderConfig config) {\r
-    this.config = config;\r
-  }\r
-\r
-  /**\r
-   * Send a PUT request to the A&AI.\r
-   *\r
-   * @param url\r
-   *          - the url\r
-   * @param transId\r
-   *          - transaction ID\r
-   * @param payload\r
-   *          - the XML or JSON payload for the request\r
-   * @param mimeType\r
-   *          - the content type (XML or JSON)\r
-   * @return ClientResponse\r
-   */\r
-  public ClientResponse putResource(String url, String payload, String transId, MimeType mimeType) {\r
-    ClientResponse result = null;\r
-    ByteArrayOutputStream baos = new ByteArrayOutputStream();\r
-    long startTimeInMs = 0;\r
-    MdcOverride override = new MdcOverride();\r
-\r
-    try {\r
-      Client client = setupClient();\r
-\r
-      baos = new ByteArrayOutputStream();\r
-      PrintStream ps = new PrintStream(baos);\r
-      if (logger.isDebugEnabled()) {\r
-        client.addFilter(new LoggingFilter(ps));\r
-      }\r
-\r
-      // Grab the current time so that we can use it for metrics purposes later.\r
-      startTimeInMs = System.currentTimeMillis();\r
-      override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs));\r
-\r
-      if (useBasicAuth()) {\r
-        result = client.resource(url).header(HEADER_TRANS_ID, transId)\r
-            .header(HEADER_FROM_APP_ID, ML_APP_NAME)\r
-            .header(HEADER_AUTHORIZATION, getAuthenticationCredentials())\r
-            .type(mimeType.getHttpHeaderType()).put(ClientResponse.class, payload);\r
-      } else {\r
-        result = client.resource(url).header(HEADER_TRANS_ID, transId)\r
-            .header(HEADER_FROM_APP_ID, ML_APP_NAME).type(mimeType.getHttpHeaderType())\r
-            .put(ClientResponse.class, payload);\r
-      }\r
-    } catch (Exception ex) {\r
-      logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "PUT", url, ex.getLocalizedMessage());\r
-      return null;\r
-    } finally {\r
-      if (logger.isDebugEnabled()) {\r
-        logger.debug(baos.toString());\r
-      }\r
-    }\r
-\r
-    if ((result != null) && ((result.getStatus() == Response.Status.CREATED.getStatusCode())\r
-        || (result.getStatus() == Response.Status.OK.getStatusCode()))) {\r
-      logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "PUT", url,\r
-          Integer.toString(result.getStatus()));\r
-      metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS,\r
-          new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus())\r
-              .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION,\r
-                  result.getResponseStatus().toString()),\r
-          override, "PUT", url, Integer.toString(result.getStatus()));\r
-    } else {\r
-      // If response is not 200 OK, then additionally log the reason\r
-      String respMsg = result.getEntity(String.class);\r
-      if (respMsg == null) {\r
-        respMsg = result.getStatusInfo().getReasonPhrase();\r
-      }\r
-      logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL, "PUT", url,\r
-          Integer.toString(result.getStatus()), respMsg);\r
-      metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL,\r
-          new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus())\r
-              .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION,\r
-                  result.getResponseStatus().toString()),\r
-          override, "PUT", url, Integer.toString(result.getStatus()), respMsg);\r
-    }\r
-\r
-    return result;\r
-  }\r
-\r
-  /**\r
-   * Send a DELETE request to the A&AI.\r
-   *\r
-   * @param url\r
-   *          - the url\r
-   * @param resourceVersion\r
-   *          - the resource-version of the model to delete\r
-   * @param transId\r
-   *          - transaction ID\r
-   * @return ClientResponse\r
-   */\r
-  public ClientResponse deleteResource(String url, String resourceVersion, String transId) {\r
-    ClientResponse result = null;\r
-    ByteArrayOutputStream baos = new ByteArrayOutputStream();\r
-    long startTimeInMs = 0;\r
-    MdcOverride override = new MdcOverride();\r
-\r
-    try {\r
-      Client client = setupClient();\r
-\r
-      baos = new ByteArrayOutputStream();\r
-      PrintStream ps = new PrintStream(baos);\r
-      if (logger.isDebugEnabled()) {\r
-        client.addFilter(new LoggingFilter(ps));\r
-      }\r
-\r
-      // Grab the current time so that we can use it for metrics purposes later.\r
-      startTimeInMs = System.currentTimeMillis();\r
-      override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs));\r
-\r
-      if (useBasicAuth()) {\r
-        result = client.resource(url).queryParam(RESOURCE_VERSION_PARAM, resourceVersion)\r
-            .header(HEADER_TRANS_ID, transId).header(HEADER_FROM_APP_ID, ML_APP_NAME)\r
-            .header(HEADER_AUTHORIZATION, getAuthenticationCredentials())\r
-            .delete(ClientResponse.class);\r
-      } else {\r
-        result = client.resource(url).queryParam(RESOURCE_VERSION_PARAM, resourceVersion)\r
-            .header(HEADER_TRANS_ID, transId).header(HEADER_FROM_APP_ID, ML_APP_NAME)\r
-            .delete(ClientResponse.class);\r
-      }\r
-    } catch (Exception ex) {\r
-      logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "DELETE", url, ex.getLocalizedMessage());\r
-      return null;\r
-    } finally {\r
-      if (logger.isDebugEnabled()) {\r
-        logger.debug(baos.toString());\r
-      }\r
-    }\r
-\r
-    logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "DELETE", url,\r
-        Integer.toString(result.getStatus()));\r
-    metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS,\r
-        new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus()).setField(\r
-            LogLine.DefinedFields.RESPONSE_DESCRIPTION, result.getResponseStatus().toString()),\r
-        override, "DELETE", url, Integer.toString(result.getStatus()));\r
-\r
-    return result;\r
-  }\r
-\r
-  /**\r
-   * Send a GET request to the A&AI for a resource.\r
-   *\r
-   * @param url\r
-   *          - the url to use\r
-   * @param transId\r
-   *          - transaction ID\r
-   * @return ClientResponse\r
-   */\r
-  public ClientResponse getResource(String url, String transId, MimeType mimeType) {\r
-    ClientResponse result = null;\r
-    ByteArrayOutputStream baos = new ByteArrayOutputStream();\r
-    long startTimeInMs = 0;\r
-    MdcOverride override = new MdcOverride();\r
-\r
-    try {\r
-      Client client = setupClient();\r
-\r
-      baos = new ByteArrayOutputStream();\r
-      PrintStream ps = new PrintStream(baos);\r
-      if (logger.isDebugEnabled()) {\r
-        client.addFilter(new LoggingFilter(ps));\r
-      }\r
-\r
-      // Grab the current time so that we can use it for metrics purposes later.\r
-      startTimeInMs = System.currentTimeMillis();\r
-      override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs));\r
-\r
-      if (useBasicAuth()) {\r
-        result = client.resource(url).header(HEADER_TRANS_ID, transId)\r
-            .header(HEADER_FROM_APP_ID, ML_APP_NAME).accept(mimeType.getHttpHeaderType())\r
-            .header(HEADER_AUTHORIZATION, getAuthenticationCredentials()).get(ClientResponse.class);\r
-      } else {\r
-        result = client.resource(url).header(HEADER_TRANS_ID, transId)\r
-            .header(HEADER_FROM_APP_ID, ML_APP_NAME).accept(mimeType.getHttpHeaderType())\r
-            .get(ClientResponse.class);\r
-\r
-      }\r
-    } catch (Exception ex) {\r
-      logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "GET", url, ex.getLocalizedMessage());\r
-      return null;\r
-    } finally {\r
-      if (logger.isDebugEnabled()) {\r
-        logger.debug(baos.toString());\r
-      }\r
-    }\r
-\r
-    logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "GET", url,\r
-        Integer.toString(result.getStatus()));\r
-    metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS,\r
-        new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus()).setField(\r
-            LogLine.DefinedFields.RESPONSE_DESCRIPTION, result.getResponseStatus().toString()),\r
-        override, "GET", url, Integer.toString(result.getStatus()));\r
-\r
-    return result;\r
-  }\r
-\r
-  /**\r
-   * Does a GET on a resource to retrieve the resource version, and then DELETE\r
-   * that version.\r
-   *\r
-   * @param url\r
-   *          - the url\r
-   * @param transId\r
-   *          - transaction ID\r
-   * @return ClientResponse\r
-   */\r
-  public ClientResponse getAndDeleteResource(String url, String transId) {\r
-    // First, GET the model\r
-    ClientResponse getResponse = getResource(url, transId, MimeType.XML);\r
-    if ((getResponse == null) || (getResponse.getStatus() != Response.Status.OK.getStatusCode())) {\r
-      return getResponse;\r
-    }\r
-\r
-    // Delete the model using the resource version in the response\r
-    String resVersion = null;\r
-    try {\r
-      resVersion = getResourceVersion(getResponse);\r
-    } catch (Exception e) {\r
-      logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "GET", url, e.getLocalizedMessage());\r
-      return null;\r
-    }\r
-\r
-    return deleteResource(url, resVersion, transId);\r
-  }\r
-\r
-  private Client setupClient() throws IOException, GeneralSecurityException {\r
-    ClientConfig clientConfig = new DefaultClientConfig();\r
-\r
-    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {\r
-      @Override\r
-      public boolean verify(String string, SSLSession ssls) {\r
-        return true;\r
-      }\r
-    });\r
-\r
-    // Create a trust manager that does not validate certificate chains\r
-    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {\r
-      @Override\r
-      public X509Certificate[] getAcceptedIssuers() {\r
-        return null;\r
-      }\r
-\r
-      @Override\r
-      public void checkClientTrusted(X509Certificate[] certs, String authType) {}\r
-\r
-      @Override\r
-      public void checkServerTrusted(X509Certificate[] certs, String authType) {}\r
-    } };\r
-\r
-    SSLContext ctx = SSLContext.getInstance("TLS");\r
-    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");\r
-    FileInputStream fin = new FileInputStream(config.getAaiKeyStorePath());\r
-    KeyStore ks = KeyStore.getInstance("PKCS12");\r
-    char[] pwd = config.getAaiKeyStorePassword().toCharArray();\r
-    ks.load(fin, pwd);\r
-    kmf.init(ks, pwd);\r
-\r
-    ctx.init(kmf.getKeyManagers(), trustAllCerts, null);\r
-    clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,\r
-        new HTTPSProperties(new HostnameVerifier() {\r
-          @Override\r
-          public boolean verify(String theString, SSLSession sslSession) {\r
-            return true;\r
-          }\r
-        }, ctx));\r
-\r
-    Client client = Client.create(clientConfig);\r
-\r
-    return client;\r
-  }\r
-\r
-  private String getResourceVersion(ClientResponse response)\r
-      throws ParserConfigurationException, SAXException, IOException {\r
-    String respData = response.getEntity(String.class);\r
-\r
-    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();\r
-    DocumentBuilder builder = factory.newDocumentBuilder();\r
-    InputSource is = new InputSource(new StringReader(respData));\r
-    Document doc = builder.parse(is);\r
-\r
-    NodeList nodeList = doc.getDocumentElement().getChildNodes();\r
-    for (int i = 0; i < nodeList.getLength(); i++) {\r
-      Node currentNode = nodeList.item(i);\r
-      if (currentNode.getNodeName().equals(RESOURCE_VERSION_PARAM)) {\r
-        return currentNode.getTextContent();\r
-      }\r
-    }\r
-\r
-    return null;\r
-  }\r
-\r
-  private String getAuthenticationCredentials() {\r
-\r
-    String usernameAndPassword = config.getAaiAuthenticationUser() + ":"\r
-        + config.getAaiAuthenticationPassword();\r
-    return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes());\r
-  }\r
-\r
-  public boolean useBasicAuth() {\r
-    return (config.getAaiAuthenticationUser() != null)\r
-        && (config.getAaiAuthenticationPassword() != null);\r
-  }\r
-}\r
+/**
+ * ============LICENSE_START=======================================================
+ * Model Loader
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.openecomp.modelloader.restclient;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.client.filter.LoggingFilter;
+import com.sun.jersey.client.urlconnection.HTTPSProperties;
+import org.openecomp.cl.api.LogFields;
+import org.openecomp.cl.api.LogLine;
+import org.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+import org.openecomp.cl.mdc.MdcContext;
+import org.openecomp.cl.mdc.MdcOverride;
+import org.openecomp.modelloader.config.ModelLoaderConfig;
+import org.openecomp.modelloader.service.ModelLoaderMsgs;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.StringReader;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import java.text.SimpleDateFormat;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.ws.rs.core.Response;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+public class AaiRestClient {
+  public enum MimeType {
+    XML("application/xml"), JSON("application/json");
+
+    private String httpType;
+
+    MimeType(String httpType) {
+      this.httpType = httpType;
+    }
+
+    String getHttpHeaderType() {
+      return httpType;
+    }
+  }
+
+  private static String HEADER_TRANS_ID = "X-TransactionId";
+  private static String HEADER_FROM_APP_ID = "X-FromAppId";
+  private static String HEADER_AUTHORIZATION = "Authorization";
+  private static String ML_APP_NAME = "ModelLoader";
+  private static String RESOURCE_VERSION_PARAM = "resource-version";
+
+  private static SimpleDateFormat dateFormatter = new SimpleDateFormat(
+      "yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
+
+  private static Logger logger = LoggerFactory.getInstance()
+      .getLogger(AaiRestClient.class.getName());
+  private static Logger metricsLogger = LoggerFactory.getInstance()
+      .getMetricsLogger(AaiRestClient.class.getName());
+
+  private ModelLoaderConfig config = null;
+
+  public AaiRestClient(ModelLoaderConfig config) {
+    this.config = config;
+  }
+
+  /**
+   * Send a PUT request to the A&AI.
+   *
+   * @param url
+   *          - the url
+   * @param transId
+   *          - transaction ID
+   * @param payload
+   *          - the XML or JSON payload for the request
+   * @param mimeType
+   *          - the content type (XML or JSON)
+   * @return ClientResponse
+   */
+  public ClientResponse putResource(String url, String payload, String transId, MimeType mimeType) {
+    ClientResponse result = null;
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    long startTimeInMs = 0;
+    MdcOverride override = new MdcOverride();
+
+    try {
+      Client client = setupClient();
+
+      baos = new ByteArrayOutputStream();
+      PrintStream ps = new PrintStream(baos);
+      if (logger.isDebugEnabled()) {
+        client.addFilter(new LoggingFilter(ps));
+      }
+
+      // Grab the current time so that we can use it for metrics purposes later.
+      startTimeInMs = System.currentTimeMillis();
+      override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs));
+
+      if (useBasicAuth()) {
+        result = client.resource(url).header(HEADER_TRANS_ID, transId)
+            .header(HEADER_FROM_APP_ID, ML_APP_NAME)
+            .header(HEADER_AUTHORIZATION, getAuthenticationCredentials())
+            .type(mimeType.getHttpHeaderType()).put(ClientResponse.class, payload);
+      } else {
+        result = client.resource(url).header(HEADER_TRANS_ID, transId)
+            .header(HEADER_FROM_APP_ID, ML_APP_NAME).type(mimeType.getHttpHeaderType())
+            .put(ClientResponse.class, payload);
+      }
+    } catch (Exception ex) {
+      logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "PUT", url, ex.getLocalizedMessage());
+      return null;
+    } finally {
+      if (logger.isDebugEnabled()) {
+        logger.debug(baos.toString());
+      }
+    }
+
+    if ((result != null) && ((result.getStatus() == Response.Status.CREATED.getStatusCode())
+        || (result.getStatus() == Response.Status.OK.getStatusCode()))) {
+      logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "PUT", url,
+          Integer.toString(result.getStatus()));
+      metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS,
+          new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus())
+              .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION,
+                  result.getResponseStatus().toString()),
+          override, "PUT", url, Integer.toString(result.getStatus()));
+    } else {
+      // If response is not 200 OK, then additionally log the reason
+      String respMsg = result.getEntity(String.class);
+      if (respMsg == null) {
+        respMsg = result.getStatusInfo().getReasonPhrase();
+      }
+      logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL, "PUT", url,
+          Integer.toString(result.getStatus()), respMsg);
+      metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL,
+          new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus())
+              .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION,
+                  result.getResponseStatus().toString()),
+          override, "PUT", url, Integer.toString(result.getStatus()), respMsg);
+    }
+
+    return result;
+  }
+
+  /**
+   * Send a DELETE request to the A&AI.
+   *
+   * @param url
+   *          - the url
+   * @param resourceVersion
+   *          - the resource-version of the model to delete
+   * @param transId
+   *          - transaction ID
+   * @return ClientResponse
+   */
+  public ClientResponse deleteResource(String url, String resourceVersion, String transId) {
+    ClientResponse result = null;
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    long startTimeInMs = 0;
+    MdcOverride override = new MdcOverride();
+
+    try {
+      Client client = setupClient();
+
+      baos = new ByteArrayOutputStream();
+      PrintStream ps = new PrintStream(baos);
+      if (logger.isDebugEnabled()) {
+        client.addFilter(new LoggingFilter(ps));
+      }
+
+      // Grab the current time so that we can use it for metrics purposes later.
+      startTimeInMs = System.currentTimeMillis();
+      override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs));
+
+      if (useBasicAuth()) {
+        result = client.resource(url).queryParam(RESOURCE_VERSION_PARAM, resourceVersion)
+            .header(HEADER_TRANS_ID, transId).header(HEADER_FROM_APP_ID, ML_APP_NAME)
+            .header(HEADER_AUTHORIZATION, getAuthenticationCredentials())
+            .delete(ClientResponse.class);
+      } else {
+        result = client.resource(url).queryParam(RESOURCE_VERSION_PARAM, resourceVersion)
+            .header(HEADER_TRANS_ID, transId).header(HEADER_FROM_APP_ID, ML_APP_NAME)
+            .delete(ClientResponse.class);
+      }
+    } catch (Exception ex) {
+      logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "DELETE", url, ex.getLocalizedMessage());
+      return null;
+    } finally {
+      if (logger.isDebugEnabled()) {
+        logger.debug(baos.toString());
+      }
+    }
+
+    logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "DELETE", url,
+        Integer.toString(result.getStatus()));
+    metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS,
+        new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus()).setField(
+            LogLine.DefinedFields.RESPONSE_DESCRIPTION, result.getResponseStatus().toString()),
+        override, "DELETE", url, Integer.toString(result.getStatus()));
+
+    return result;
+  }
+
+  /**
+   * Send a GET request to the A&AI for a resource.
+   *
+   * @param url
+   *          - the url to use
+   * @param transId
+   *          - transaction ID
+   * @return ClientResponse
+   */
+  public ClientResponse getResource(String url, String transId, MimeType mimeType) {
+    ClientResponse result = null;
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    long startTimeInMs = 0;
+    MdcOverride override = new MdcOverride();
+
+    try {
+      Client client = setupClient();
+
+      baos = new ByteArrayOutputStream();
+      PrintStream ps = new PrintStream(baos);
+      if (logger.isDebugEnabled()) {
+        client.addFilter(new LoggingFilter(ps));
+      }
+
+      // Grab the current time so that we can use it for metrics purposes later.
+      startTimeInMs = System.currentTimeMillis();
+      override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs));
+
+      if (useBasicAuth()) {
+        result = client.resource(url).header(HEADER_TRANS_ID, transId)
+            .header(HEADER_FROM_APP_ID, ML_APP_NAME).accept(mimeType.getHttpHeaderType())
+            .header(HEADER_AUTHORIZATION, getAuthenticationCredentials()).get(ClientResponse.class);
+      } else {
+        result = client.resource(url).header(HEADER_TRANS_ID, transId)
+            .header(HEADER_FROM_APP_ID, ML_APP_NAME).accept(mimeType.getHttpHeaderType())
+            .get(ClientResponse.class);
+
+      }
+    } catch (Exception ex) {
+      logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "GET", url, ex.getLocalizedMessage());
+      return null;
+    } finally {
+      if (logger.isDebugEnabled()) {
+        logger.debug(baos.toString());
+      }
+    }
+
+    logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "GET", url,
+        Integer.toString(result.getStatus()));
+    metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS,
+        new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus()).setField(
+            LogLine.DefinedFields.RESPONSE_DESCRIPTION, result.getResponseStatus().toString()),
+        override, "GET", url, Integer.toString(result.getStatus()));
+
+    return result;
+  }
+
+  /**
+   * Send a POST request to the A&AI.
+   *
+   * @param url
+   *          - the url
+   * @param transId
+   *          - transaction ID
+   * @param payload
+   *          - the XML or JSON payload for the request
+   * @param mimeType
+   *          - the content type (XML or JSON)
+   * @return ClientResponse
+   */
+  public ClientResponse postResource(String url, String payload, String transId, MimeType mimeType) {
+    ClientResponse result = null;
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    long startTimeInMs = 0;
+    MdcOverride override = new MdcOverride();
+
+    try {
+      Client client = setupClient();
+
+      baos = new ByteArrayOutputStream();
+      PrintStream ps = new PrintStream(baos);
+      if (logger.isDebugEnabled()) {
+        client.addFilter(new LoggingFilter(ps));
+      }
+
+      // Grab the current time so that we can use it for metrics purposes later.
+      startTimeInMs = System.currentTimeMillis();
+      override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs));
+
+      if (useBasicAuth()) {
+        result = client.resource(url).header(HEADER_TRANS_ID, transId)
+            .header(HEADER_FROM_APP_ID, ML_APP_NAME)
+            .header(HEADER_AUTHORIZATION, getAuthenticationCredentials())
+            .type(mimeType.getHttpHeaderType()).post(ClientResponse.class, payload);
+      } else {
+        result = client.resource(url).header(HEADER_TRANS_ID, transId)
+            .header(HEADER_FROM_APP_ID, ML_APP_NAME).type(mimeType.getHttpHeaderType())
+            .post(ClientResponse.class, payload);
+      }
+    } catch (Exception ex) {
+      logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "POST", url, ex.getLocalizedMessage());
+      return null;
+    } finally {
+      if (logger.isDebugEnabled()) {
+        logger.debug(baos.toString());
+      }
+    }
+
+    if ((result != null) && ((result.getStatus() == Response.Status.CREATED.getStatusCode())
+        || (result.getStatus() == Response.Status.OK.getStatusCode()))) {
+      logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "POST", url,
+          Integer.toString(result.getStatus()));
+      metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS,
+          new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus())
+              .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION,
+                  result.getResponseStatus().toString()),
+          override, "POST", url, Integer.toString(result.getStatus()));
+    } else {
+      // If response is not 200 OK, then additionally log the reason
+      String respMsg = result.getEntity(String.class);
+      if (respMsg == null) {
+        respMsg = result.getStatusInfo().getReasonPhrase();
+      }
+      logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL, "POST", url,
+          Integer.toString(result.getStatus()), respMsg);
+      metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL,
+          new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus())
+              .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION,
+                  result.getResponseStatus().toString()),
+          override, "POST", url, Integer.toString(result.getStatus()), respMsg);
+    }
+
+    return result;
+  }
+  
+  /**
+   * Does a GET on a resource to retrieve the resource version, and then DELETE
+   * that version.
+   *
+   * @param url
+   *          - the url
+   * @param transId
+   *          - transaction ID
+   * @return ClientResponse
+   */
+  public ClientResponse getAndDeleteResource(String url, String transId) {
+    // First, GET the model
+    ClientResponse getResponse = getResource(url, transId, MimeType.XML);
+    if ((getResponse == null) || (getResponse.getStatus() != Response.Status.OK.getStatusCode())) {
+      return getResponse;
+    }
+
+    // Delete the model using the resource version in the response
+    String resVersion = null;
+    try {
+      resVersion = getResourceVersion(getResponse);
+    } catch (Exception e) {
+      logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "GET", url, e.getLocalizedMessage());
+      return null;
+    }
+
+    return deleteResource(url, resVersion, transId);
+  }
+
+  private Client setupClient() throws IOException, GeneralSecurityException {
+    ClientConfig clientConfig = new DefaultClientConfig();
+
+    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
+      @Override
+      public boolean verify(String string, SSLSession ssls) {
+        return true;
+      }
+    });
+
+    // Create a trust manager that does not validate certificate chains
+    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+      @Override
+      public X509Certificate[] getAcceptedIssuers() {
+        return null;
+      }
+
+      @Override
+      public void checkClientTrusted(X509Certificate[] certs, String authType) {}
+
+      @Override
+      public void checkServerTrusted(X509Certificate[] certs, String authType) {}
+    } };
+
+    SSLContext ctx = SSLContext.getInstance("TLS");
+    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+    FileInputStream fin = new FileInputStream(config.getAaiKeyStorePath());
+    KeyStore ks = KeyStore.getInstance("PKCS12");
+    char[] pwd = config.getAaiKeyStorePassword().toCharArray();
+    ks.load(fin, pwd);
+    kmf.init(ks, pwd);
+
+    ctx.init(kmf.getKeyManagers(), trustAllCerts, null);
+    clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
+        new HTTPSProperties(new HostnameVerifier() {
+          @Override
+          public boolean verify(String theString, SSLSession sslSession) {
+            return true;
+          }
+        }, ctx));
+
+    Client client = Client.create(clientConfig);
+
+    return client;
+  }
+
+  private String getResourceVersion(ClientResponse response)
+      throws ParserConfigurationException, SAXException, IOException {
+    String respData = response.getEntity(String.class);
+
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    DocumentBuilder builder = factory.newDocumentBuilder();
+    InputSource is = new InputSource(new StringReader(respData));
+    Document doc = builder.parse(is);
+
+    NodeList nodeList = doc.getDocumentElement().getChildNodes();
+    for (int i = 0; i < nodeList.getLength(); i++) {
+      Node currentNode = nodeList.item(i);
+      if (currentNode.getNodeName().equals(RESOURCE_VERSION_PARAM)) {
+        return currentNode.getTextContent();
+      }
+    }
+
+    return null;
+  }
+
+  private String getAuthenticationCredentials() {
+
+    String usernameAndPassword = config.getAaiAuthenticationUser() + ":"
+        + config.getAaiAuthenticationPassword();
+    return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes());
+  }
+
+  public boolean useBasicAuth() {
+    return (config.getAaiAuthenticationUser() != null)
+        && (config.getAaiAuthenticationPassword() != null);
+  }
+}