summaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authormark.j.leonard <mark.j.leonard@gmail.com>2018-06-07 16:45:38 +0100
committermark.j.leonard <mark.j.leonard@gmail.com>2018-06-07 17:17:30 +0100
commit7e6fe8c29c5a5cfa5caf6ab47b30280e1fc20432 (patch)
treeaf9e48c7bf85ae68d42cbc94df60589bdd7e052e /src/main
parentc5aea4a8bc398fc1c6220875e55b9520fd7f7524 (diff)
Add support for loading VNF Catalog XML files
Issue-ID: AAI-1214 Change-Id: I5d0eb3456916e6f3e5ba3a9b4e828feaff0cde4e Signed-off-by: mark.j.leonard <mark.j.leonard@gmail.com>
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java67
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/ArtifactType.java3
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifact.java1
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifactHandler.java190
-rw-r--r--src/main/java/org/onap/aai/modelloader/extraction/VnfCatalogExtractor.java107
-rw-r--r--src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java36
-rw-r--r--src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java2
-rw-r--r--src/main/java/org/onap/aai/modelloader/service/ModelLoaderMsgs.java245
-rw-r--r--src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java4
-rw-r--r--src/main/resources/org/onap/aai/modelloader/service/ModelLoaderMsgs.properties6
10 files changed, 455 insertions, 206 deletions
diff --git a/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java b/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java
index 0a2bc85..01505ba 100644
--- a/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java
+++ b/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java
@@ -21,6 +21,8 @@
package org.onap.aai.modelloader.config;
import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@@ -47,29 +49,29 @@ public class ModelLoaderConfig implements IConfiguration {
private static final String SUFFIX_TRUSTSTORE_PASS = "TRUSTSTORE_PASSWORD";
// Configuration file properties
- protected static final String PROP_ML_DISTRIBUTION_ACTIVE_SERVER_TLS_AUTH = PREFIX_DISTRIBUTION_CLIENT
- + "ACTIVE_SERVER_TLS_AUTH";
- protected static final String PROP_ML_DISTRIBUTION_ASDC_CONNECTION_DISABLED = PREFIX_DISTRIBUTION_CLIENT
- + "ASDC_CONNECTION_DISABLE";
+ protected static final String PROP_ML_DISTRIBUTION_ACTIVE_SERVER_TLS_AUTH =
+ PREFIX_DISTRIBUTION_CLIENT + "ACTIVE_SERVER_TLS_AUTH";
+ protected static final String PROP_ML_DISTRIBUTION_ASDC_CONNECTION_DISABLED =
+ PREFIX_DISTRIBUTION_CLIENT + "ASDC_CONNECTION_DISABLE";
protected static final String PROP_ML_DISTRIBUTION_ASDC_ADDRESS = PREFIX_DISTRIBUTION_CLIENT + "ASDC_ADDRESS";
protected static final String PROP_ML_DISTRIBUTION_CONSUMER_GROUP = PREFIX_DISTRIBUTION_CLIENT + "CONSUMER_GROUP";
protected static final String PROP_ML_DISTRIBUTION_CONSUMER_ID = PREFIX_DISTRIBUTION_CLIENT + "CONSUMER_ID";
- protected static final String PROP_ML_DISTRIBUTION_ENVIRONMENT_NAME = PREFIX_DISTRIBUTION_CLIENT
- + "ENVIRONMENT_NAME";
- protected static final String PROP_ML_DISTRIBUTION_KEYSTORE_PASSWORD = PREFIX_DISTRIBUTION_CLIENT
- + SUFFIX_KEYSTORE_PASS;
- protected static final String PROP_ML_DISTRIBUTION_KEYSTORE_FILE = PREFIX_DISTRIBUTION_CLIENT
- + SUFFIX_KEYSTORE_FILE;
+ protected static final String PROP_ML_DISTRIBUTION_ENVIRONMENT_NAME =
+ PREFIX_DISTRIBUTION_CLIENT + "ENVIRONMENT_NAME";
+ protected static final String PROP_ML_DISTRIBUTION_KEYSTORE_PASSWORD =
+ PREFIX_DISTRIBUTION_CLIENT + SUFFIX_KEYSTORE_PASS;
+ protected static final String PROP_ML_DISTRIBUTION_KEYSTORE_FILE =
+ PREFIX_DISTRIBUTION_CLIENT + SUFFIX_KEYSTORE_FILE;
protected static final String PROP_ML_DISTRIBUTION_PASSWORD = PREFIX_DISTRIBUTION_CLIENT + "PASSWORD";
- protected static final String PROP_ML_DISTRIBUTION_POLLING_INTERVAL = PREFIX_DISTRIBUTION_CLIENT
- + "POLLING_INTERVAL";
+ protected static final String PROP_ML_DISTRIBUTION_POLLING_INTERVAL =
+ PREFIX_DISTRIBUTION_CLIENT + "POLLING_INTERVAL";
protected static final String PROP_ML_DISTRIBUTION_POLLING_TIMEOUT = PREFIX_DISTRIBUTION_CLIENT + "POLLING_TIMEOUT";
protected static final String PROP_ML_DISTRIBUTION_USER = PREFIX_DISTRIBUTION_CLIENT + "USER";
protected static final String PROP_ML_DISTRIBUTION_ARTIFACT_TYPES = PREFIX_DISTRIBUTION_CLIENT + "ARTIFACT_TYPES";
- protected static final String PROP_ML_DISTRIBUTION_MSG_BUS_ADDRESSES = PREFIX_DISTRIBUTION_CLIENT
- + "MSG_BUS_ADDRESSES";
- protected static final String PROP_ML_DISTRIBUTION_HTTPS_WITH_DMAAP = PREFIX_DISTRIBUTION_CLIENT
- + "USE_HTTPS_WITH_DMAAP";
+ protected static final String PROP_ML_DISTRIBUTION_MSG_BUS_ADDRESSES =
+ PREFIX_DISTRIBUTION_CLIENT + "MSG_BUS_ADDRESSES";
+ protected static final String PROP_ML_DISTRIBUTION_HTTPS_WITH_DMAAP =
+ PREFIX_DISTRIBUTION_CLIENT + "USE_HTTPS_WITH_DMAAP";
protected static final String PROP_AAI_BASE_URL = PREFIX_AAI + "BASE_URL";
protected static final String PROP_AAI_KEYSTORE_FILE = PREFIX_AAI + SUFFIX_KEYSTORE_FILE;
@@ -88,29 +90,16 @@ public class ModelLoaderConfig implements IConfiguration {
protected static final String PROP_BABEL_GENERATE_RESOURCE_URL = PREFIX_BABEL + "GENERATE_ARTIFACTS_URL";
protected static final String PROP_DEBUG_INGEST_SIMULATOR = PREFIX_DEBUG + "INGEST_SIMULATOR";
- private static String configHome;
+ protected static final String FILESEP =
+ (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator");
+ private static String configHome;
private Properties modelLoaderProperties = null;
-
private String certLocation = ".";
-
private List<String> artifactTypes = null;
-
private List<String> msgBusAddrs = null;
-
private String modelVersion = null;
- protected static final String FILESEP = (System.getProperty("file.separator") == null) ? "/"
- : System.getProperty("file.separator");
-
- public static void setConfigHome(String configHome) {
- ModelLoaderConfig.configHome = configHome;
- }
-
- public static String propertiesFile() {
- return configHome + FILESEP + "model-loader.properties";
- }
-
public ModelLoaderConfig(Properties configProperties) {
this(configProperties, ModelLoaderConfig.configHome + FILESEP + "auth" + FILESEP);
}
@@ -118,10 +107,8 @@ public class ModelLoaderConfig implements IConfiguration {
/**
* Original constructor
*
- * @param modelLoaderProperties
- * properties needed to be configured for the model loader
- * @param certLocation
- * location of the certificate
+ * @param modelLoaderProperties properties needed to be configured for the model loader
+ * @param certLocation location of the certificate
*/
public ModelLoaderConfig(Properties modelLoaderProperties, String certLocation) {
this.modelLoaderProperties = modelLoaderProperties;
@@ -146,6 +133,14 @@ public class ModelLoaderConfig implements IConfiguration {
}
}
+ public static void setConfigHome(String configHome) {
+ ModelLoaderConfig.configHome = configHome;
+ }
+
+ public static Path propertiesFile() {
+ return Paths.get(configHome, "model-loader.properties");
+ }
+
@Override
public boolean activateServerTLSAuth() {
String value = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ACTIVE_SERVER_TLS_AUTH);
diff --git a/src/main/java/org/onap/aai/modelloader/entity/ArtifactType.java b/src/main/java/org/onap/aai/modelloader/entity/ArtifactType.java
index a58c874..587b474 100644
--- a/src/main/java/org/onap/aai/modelloader/entity/ArtifactType.java
+++ b/src/main/java/org/onap/aai/modelloader/entity/ArtifactType.java
@@ -24,5 +24,6 @@ public enum ArtifactType {
MODEL,
MODEL_V8,
NAMED_QUERY,
- VNF_CATALOG;
+ VNF_CATALOG,
+ VNF_CATALOG_XML;
}
diff --git a/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifact.java b/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifact.java
index 9a84cf2..7447726 100644
--- a/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifact.java
+++ b/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifact.java
@@ -28,6 +28,7 @@ public class VnfCatalogArtifact extends Artifact {
public VnfCatalogArtifact(String payload) {
this(ArtifactType.VNF_CATALOG, payload);
}
+
public VnfCatalogArtifact(ArtifactType artifactType, String payload) {
super(artifactType);
setPayload(payload);
diff --git a/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifactHandler.java b/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifactHandler.java
index 3480c68..c54d7b2 100644
--- a/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifactHandler.java
+++ b/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifactHandler.java
@@ -1,5 +1,5 @@
/**
- * ============LICENSE_START=======================================================
+ * ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
* Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
@@ -22,14 +22,20 @@ package org.onap.aai.modelloader.entity.catalog;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
-import java.io.UnsupportedEncodingException;
+import java.io.StringReader;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.text.StringEscapeUtils;
+import org.apache.http.client.utils.URIBuilder;
import org.onap.aai.cl.api.Logger;
import org.onap.aai.cl.eelf.LoggerFactory;
import org.onap.aai.modelloader.config.ModelLoaderConfig;
@@ -38,7 +44,11 @@ import org.onap.aai.modelloader.entity.ArtifactHandler;
import org.onap.aai.modelloader.restclient.AaiRestClient;
import org.onap.aai.modelloader.service.ModelLoaderMsgs;
import org.onap.aai.restclient.client.OperationResult;
-import org.springframework.web.util.UriUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
/**
* VNF Catalog specific handling
@@ -80,11 +90,47 @@ public class VnfCatalogArtifactHandler extends ArtifactHandler {
return true;
}
+ /*
+ * If something fails in the middle of ingesting the catalog we want to roll back any changes to the DB
+ */
+ @Override
+ public void rollback(List<Artifact> completedArtifacts, String distributionId, AaiRestClient aaiClient) {
+ for (Artifact completedArtifact : completedArtifacts) {
+ Map<String, String> data = new Gson().fromJson(completedArtifact.getPayload(),
+ new TypeToken<Map<String, String>>() {}.getType());
+ String url = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/" + data.get(ATTR_UUID);
+ // Try to delete the image. If something goes wrong we can't really do anything here
+ aaiClient.getAndDeleteResource(url, distributionId);
+ }
+ }
+
private void distributeVnfcData(AaiRestClient restClient, String distributionId, Artifact vnfcArtifact,
List<Artifact> completedArtifacts) throws VnfImageException {
+ List<Map<String, String>> vnfcData;
+ switch (vnfcArtifact.getType()) {
+ case VNF_CATALOG:
+ vnfcData = unmarshallVnfcData(vnfcArtifact);
+ break;
+ case VNF_CATALOG_XML:
+ vnfcData = parseXmlVnfcData(vnfcArtifact);
+ break;
+ default:
+ throw new VnfImageException("Unsupported type " + vnfcArtifact.getType());
+ }
+ distributeVnfcData(restClient, distributionId, completedArtifacts, vnfcData);
+ }
- List<Map<String, String>> vnfcData = unmarshallVnfcData(vnfcArtifact);
-
+ /**
+ * Build a VNF image from each of the supplied data items, and distribute to AAI
+ *
+ * @param restClient
+ * @param distributionId
+ * @param completedArtifacts
+ * @param vnfcData
+ * @throws VnfImageException
+ */
+ private void distributeVnfcData(AaiRestClient restClient, String distributionId, List<Artifact> completedArtifacts,
+ List<Map<String, String>> vnfcData) throws VnfImageException {
for (Map<String, String> dataItem : vnfcData) {
// If an empty dataItem is supplied, do nothing.
if (dataItem.isEmpty()) {
@@ -92,49 +138,47 @@ public class VnfCatalogArtifactHandler extends ArtifactHandler {
continue;
}
- String urlParams;
- StringBuilder imageId = new StringBuilder("vnf image");
-
- try {
- urlParams = buildUrlImgIdStrings(imageId, dataItem);
- } catch (UnsupportedEncodingException e) {
- throw new VnfImageException(e);
+ StringBuilder imageIdBuilder = new StringBuilder("vnf image");
+ for (Entry<String, String> entry : dataItem.entrySet()) {
+ imageIdBuilder.append(" ").append(entry.getValue());
}
+ String imageId = imageIdBuilder.toString();
+ int resultCode = getVnfImage(restClient, distributionId, imageId, dataItem);
- OperationResult tryGet =
- restClient.getResource(config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "?" + urlParams,
- distributionId, MediaType.APPLICATION_JSON_TYPE);
-
- if (tryGet == null) {
- throw new VnfImageException(imageId.toString());
- }
-
- int resultCode = tryGet.getResultCode();
if (resultCode == Response.Status.NOT_FOUND.getStatusCode()) {
// This vnf-image is missing, so add it
boolean success = putVnfImage(restClient, dataItem, distributionId);
- if (!success) {
- throw new VnfImageException(imageId.toString());
+ if (success) {
+ completedArtifacts.add(new VnfCatalogArtifact(new Gson().toJson(dataItem)));
+ logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, imageId + " successfully ingested.");
+ } else {
+ throw new VnfImageException(imageId);
}
- completedArtifacts.add(vnfcArtifact);
- logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, imageId + " successfully ingested.");
} else if (resultCode == Response.Status.OK.getStatusCode()) {
logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, imageId + " already exists. Skipping ingestion.");
} else {
// if other than 404 or 200, something went wrong
- throw new VnfImageException(imageId.toString(), resultCode);
+ throw new VnfImageException(imageId, resultCode);
}
}
}
- private String buildUrlImgIdStrings(StringBuilder imageId, Map<String, String> dataItem)
- throws UnsupportedEncodingException {
- StringBuilder urlParams = new StringBuilder();
- for (Entry<String, String> entry : dataItem.entrySet()) {
- urlParams.append(entry.getKey()).append("=").append(UriUtils.encode(entry.getValue(), "UTF-8")).append("&");
- imageId.append(" ").append(entry.getValue());
+ private int getVnfImage(AaiRestClient restClient, String distributionId, String imageId,
+ Map<String, String> dataItem) throws VnfImageException {
+ try {
+ URIBuilder b = new URIBuilder(config.getAaiBaseUrl() + config.getAaiVnfImageUrl());
+ for (Entry<String, String> entry : dataItem.entrySet()) {
+ b.addParameter(entry.getKey(), entry.getValue());
+ }
+ OperationResult tryGet =
+ restClient.getResource(b.build().toString(), distributionId, MediaType.APPLICATION_JSON_TYPE);
+ if (tryGet == null) {
+ throw new VnfImageException(imageId);
+ }
+ return tryGet.getResultCode();
+ } catch (URISyntaxException ex) {
+ throw new VnfImageException(ex);
}
- return urlParams.deleteCharAt(urlParams.length() - 1).toString();
}
private boolean putVnfImage(AaiRestClient restClient, Map<String, String> dataItem, String distributionId) {
@@ -155,19 +199,79 @@ public class VnfCatalogArtifactHandler extends ArtifactHandler {
new TypeToken<List<Map<String, String>>>() {}.getType());
}
- /*
- * If something fails in the middle of ingesting the catalog we want to roll back any changes to the DB
+ /**
+ * Parse the VNF Catalog XML and transform into Key/Value pairs.
+ *
+ * @param vnfcArtifact
+ * @return VNF Image data in Map form
+ * @throws VnfImageException
*/
- @Override
- public void rollback(List<Artifact> completedArtifacts, String distributionId, AaiRestClient aaiClient) {
- for (Artifact completedArtifact : completedArtifacts) {
- List<Map<String, String>> completedImageData = unmarshallVnfcData(completedArtifact);
- for (Map<String, String> data : completedImageData) {
- String url = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/" + data.get(ATTR_UUID);
- // Try to delete the image. If something goes wrong we can't really do anything here
- aaiClient.getAndDeleteResource(url, distributionId);
+ private List<Map<String, String>> parseXmlVnfcData(Artifact vnfcArtifact) throws VnfImageException {
+ List<Map<String, String>> vnfcData = new ArrayList<>();
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ InputSource is = new InputSource(new StringReader(vnfcArtifact.getPayload()));
+ Document doc = builder.parse(is);
+ doc.getDocumentElement().normalize();
+
+ NodeList pnl = doc.getElementsByTagName("part-number-list");
+ for (int i = 0; i < pnl.getLength(); i++) {
+ Node partNumber = pnl.item(i);
+ if (partNumber.getNodeType() == Node.ELEMENT_NODE) {
+ Element vendorInfo = getFirstChildNodeByName(partNumber, "vendor-info");
+ if (vendorInfo != null) {
+ Map<String, String> application = new HashMap<>();
+ application.put("application",
+ vendorInfo.getElementsByTagName("vendor-model").item(0).getTextContent());
+ application.put("application-vendor",
+ vendorInfo.getElementsByTagName("vendor-name").item(0).getTextContent());
+ populateSoftwareVersions(vnfcData, application, partNumber);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ throw new VnfImageException(ex);
+ }
+ return vnfcData;
+ }
+
+ /**
+ * @param vnfcData to populate
+ * @param applicationData
+ * @param partNumber
+ */
+ private void populateSoftwareVersions(List<Map<String, String>> vnfcData, Map<String, String> applicationData,
+ Node partNumber) {
+ NodeList nodes = partNumber.getChildNodes();
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Node childNode = nodes.item(i);
+ if (childNode.getNodeName().equalsIgnoreCase("software-version-list")) {
+ Element softwareVersion = getFirstChildNodeByName(childNode, "software-version");
+ if (softwareVersion != null) {
+ HashMap<String, String> vnfImageData = new HashMap<>(applicationData);
+ vnfImageData.put("application-version", softwareVersion.getTextContent());
+ vnfcData.add(vnfImageData);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param node
+ * @param childNodeName
+ * @return the first child node matching the given name
+ */
+ private Element getFirstChildNodeByName(Node node, String childNodeName) {
+ NodeList nodes = node.getChildNodes();
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Node childNode = nodes.item(i);
+ if (childNode.getNodeName().equalsIgnoreCase(childNodeName)) {
+ return (Element) childNode;
}
}
+ return null;
}
}
diff --git a/src/main/java/org/onap/aai/modelloader/extraction/VnfCatalogExtractor.java b/src/main/java/org/onap/aai/modelloader/extraction/VnfCatalogExtractor.java
new file mode 100644
index 0000000..5682774
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/extraction/VnfCatalogExtractor.java
@@ -0,0 +1,107 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017-2018 European Software Marketing Ltd.
+ * ================================================================================
+ * 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=========================================================
+ */
+package org.onap.aai.modelloader.extraction;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.regex.Pattern;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.aai.modelloader.entity.Artifact;
+import org.onap.aai.modelloader.entity.ArtifactType;
+import org.onap.aai.modelloader.entity.catalog.VnfCatalogArtifact;
+import org.onap.aai.modelloader.service.ModelLoaderMsgs;
+
+
+/**
+ * The purpose of this class is to process a .csar file in the form of a byte array and extract VNF Catalog XML files
+ * from it.
+ *
+ * A .csar file is a compressed archive like a zip file and this class will treat the byte array as it if were a zip
+ * file.
+ */
+public class VnfCatalogExtractor {
+ private static final Logger logger = LoggerFactory.getInstance().getLogger(VnfCatalogExtractor.class.getName());
+
+ private static final Pattern VNFCFILE_EXTENSION_REGEX =
+ Pattern.compile("(?i)artifacts(\\\\|\\/)deployment(\\\\|\\/)vnf_catalog(\\\\|\\/).*\\.xml$");
+
+ /**
+ * This method is responsible for filtering the contents of the supplied archive and returning a collection of
+ * {@link Artifact}s that represent the VNF Catalog files that have been found in the archive.<br>
+ * <br>
+ * If the archive contains no VNF Catalog files it will return an empty list.<br>
+ *
+ * @param archive the zip file in the form of a byte array containing zero or more VNF Catalog files
+ * @param name the name of the archive file
+ * @return List<Artifact> collection of VNF Catalog XML files found in the archive
+ * @throws InvalidArchiveException if an error occurs trying to extract the VNFC files from the archive or if the
+ * archive is not a zip file
+ */
+ public List<Artifact> extract(byte[] archive, String name) throws InvalidArchiveException {
+ validateRequest(archive, name);
+
+ logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Extracting CSAR archive: " + name);
+
+ List<Artifact> vnfcFiles = new ArrayList<>();
+ try (SeekableInMemoryByteChannel inMemoryByteChannel = new SeekableInMemoryByteChannel(archive);
+ ZipFile zipFile = new ZipFile(inMemoryByteChannel)) {
+ for (Enumeration<ZipArchiveEntry> enumeration = zipFile.getEntries(); enumeration.hasMoreElements();) {
+ ZipArchiveEntry entry = enumeration.nextElement();
+ if (fileShouldBeExtracted(entry)) {
+ vnfcFiles.add(new VnfCatalogArtifact(ArtifactType.VNF_CATALOG_XML,
+ IOUtils.toString(zipFile.getInputStream(entry))));
+ }
+ }
+ } catch (IOException e) {
+ throw new InvalidArchiveException(
+ "An error occurred trying to create a ZipFile. Is the content being converted really a csar file?",
+ e);
+ }
+
+ logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, vnfcFiles.size() + " VNF Catalog files extracted.");
+
+ return vnfcFiles;
+ }
+
+ private static void validateRequest(byte[] archive, String name) throws InvalidArchiveException {
+ if (archive == null || archive.length == 0) {
+ throw new InvalidArchiveException("An archive must be supplied for processing.");
+ } else if (StringUtils.isBlank(name)) {
+ throw new InvalidArchiveException("The name of the archive must be supplied for processing.");
+ }
+ }
+
+ private static boolean fileShouldBeExtracted(ZipArchiveEntry entry) {
+ logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Checking if " + entry.getName() + " should be extracted...");
+ boolean extractFile = VNFCFILE_EXTENSION_REGEX.matcher(entry.getName()).matches();
+ logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Keeping file: " + entry.getName() + "? : " + extractFile);
+ return extractFile;
+ }
+}
+
diff --git a/src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java b/src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java
index febc99a..58bb074 100644
--- a/src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java
+++ b/src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java
@@ -1,5 +1,5 @@
/**
- * ============LICENSE_START=======================================================
+ * ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
* Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
@@ -38,6 +38,7 @@ import org.onap.aai.modelloader.entity.model.BabelArtifactParsingException;
import org.onap.aai.modelloader.entity.model.IModelParser;
import org.onap.aai.modelloader.entity.model.NamedQueryArtifactParser;
import org.onap.aai.modelloader.extraction.InvalidArchiveException;
+import org.onap.aai.modelloader.extraction.VnfCatalogExtractor;
import org.onap.aai.modelloader.restclient.BabelServiceClient;
import org.onap.aai.modelloader.restclient.BabelServiceClientException;
import org.onap.aai.modelloader.service.BabelServiceClientFactory;
@@ -68,6 +69,7 @@ public class ArtifactDownloadManager {
private BabelArtifactConverter babelArtifactConverter;
private ModelLoaderConfig config;
private BabelServiceClientFactory clientFactory;
+ private VnfCatalogExtractor vnfCatalogExtractor;
public ArtifactDownloadManager(IDistributionClient client, ModelLoaderConfig config,
BabelServiceClientFactory clientFactory) {
@@ -149,12 +151,32 @@ public class ArtifactDownloadManager {
public void processToscaArtifacts(List<Artifact> modelArtifacts, List<Artifact> catalogArtifacts, byte[] payload,
IArtifactInfo artifactInfo, String distributionId, String serviceVersion)
+ throws ProcessToscaArtifactsException, InvalidArchiveException {
+ // Get translated artifacts from Babel Service
+ invokeBabelService(modelArtifacts, catalogArtifacts, payload, artifactInfo, distributionId, serviceVersion);
+
+ // Get VNF Catalog artifacts directly from CSAR
+ List<Artifact> csarCatalogArtifacts = getVnfCatalogExtractor().extract(payload, artifactInfo.getArtifactName());
+
+ // Throw an error if VNF Catalog data is present in the Babel payload and directly in the CSAR
+ if (!catalogArtifacts.isEmpty() && !csarCatalogArtifacts.isEmpty()) {
+ logger.error(ModelLoaderMsgs.DUPLICATE_VNFC_DATA_ERROR, artifactInfo.getArtifactName());
+ throw new InvalidArchiveException("CSAR: " + artifactInfo.getArtifactName()
+ + " contains VNF Catalog data in the format of both TOSCA and XML files. Only one format can be used for each CSAR file.");
+ } else if (!csarCatalogArtifacts.isEmpty()) {
+ catalogArtifacts.addAll(csarCatalogArtifacts);
+ }
+ }
+
+ public void invokeBabelService(List<Artifact> modelArtifacts, List<Artifact> catalogArtifacts, byte[] payload,
+ IArtifactInfo artifactInfo, String distributionId, String serviceVersion)
throws ProcessToscaArtifactsException {
try {
BabelServiceClient babelClient = createBabelServiceClient(artifactInfo, serviceVersion);
- logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT,
- "Posting artifact: " + artifactInfo.getArtifactName() + ", version: " + serviceVersion);
+ logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT,
+ "Posting artifact: " + artifactInfo.getArtifactName() + ", service version: " + serviceVersion
+ + ", artifact version: " + artifactInfo.getArtifactVersion());
List<BabelArtifact> babelArtifacts =
babelClient.postArtifact(payload, artifactInfo.getArtifactName(), serviceVersion, distributionId);
@@ -251,4 +273,12 @@ public class ArtifactDownloadManager {
return babelArtifactConverter;
}
+
+ private VnfCatalogExtractor getVnfCatalogExtractor() {
+ if (vnfCatalogExtractor == null) {
+ vnfCatalogExtractor = new VnfCatalogExtractor();
+ }
+
+ return vnfCatalogExtractor;
+ }
}
diff --git a/src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java b/src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java
index 626399e..4f552f7 100644
--- a/src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java
+++ b/src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java
@@ -52,7 +52,7 @@ public class NotificationPublisher {
public NotificationPublisher() {
Properties configProperties = new Properties();
try {
- configProperties.load(Files.newInputStream(Paths.get(ModelLoaderConfig.propertiesFile())));
+ configProperties.load(Files.newInputStream(ModelLoaderConfig.propertiesFile()));
} catch (IOException e) {
String errorMsg = "Failed to load configuration: " + e.getMessage();
logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, e, errorMsg);
diff --git a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderMsgs.java b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderMsgs.java
index fd39a9a..26a9efa 100644
--- a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderMsgs.java
+++ b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderMsgs.java
@@ -1,120 +1,125 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017-2018 European Software Marketing Ltd.
- * ================================================================================
- * 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=========================================================
- */
-package org.onap.aai.modelloader.service;
-
-import com.att.eelf.i18n.EELFResourceManager;
-import org.onap.aai.cl.eelf.LogMessageEnum;
-
-public enum ModelLoaderMsgs implements LogMessageEnum {
-
- /**
- * Arguments: None.
- */
- LOADING_CONFIGURATION,
-
- /**
- * Arguments: None.
- */
- STOPPING_CLIENT,
-
- /**
- * Arguments: {0} = message.
- */
- INITIALIZING,
-
- /**
- * Arguments: {0} = reason.
- */
- ASDC_CONNECTION_ERROR,
-
- /**
- * Arguments: {0} = message.
- */
- DISTRIBUTION_EVENT,
-
- /**
- * Arguments: {0} = error message.
- */
- DISTRIBUTION_EVENT_ERROR,
-
- /**
- * Arguments: {0} = request type. {1} = endpoint. {2} = result code.
- */
- AAI_REST_REQUEST_SUCCESS,
-
- /**
- * Arguments: {0} = request type. {1} = endpoint. {2} = result code. {3} = result. message
- */
- AAI_REST_REQUEST_UNSUCCESSFUL,
-
- /**
- * Arguments: {0} = request type. {1} = endpoint. {2} = error message.
- */
- AAI_REST_REQUEST_ERROR,
-
- /**
- * Arguments: {0} = request type. {1} = endpoint. {2} = error message.
- */
- BABEL_REST_REQUEST_ERROR,
-
- /**
- * Arguments: {0} = info request payload.
- **/
- AAI_REST_REQUEST_PAYLOAD,
-
- /**
- * Arguments: {0} = artifact name
- */
- ARTIFACT_PARSE_ERROR,
-
- /**
- * Arguments: {0} = info request payload.
- **/
- BABEL_REST_REQUEST_PAYLOAD,
-
- /**
- * Arguments: {0} = info Babel response payload.
- **/
- BABEL_RESPONSE_PAYLOAD,
-
- /**
- * Arguments: {0} = artifact name. {1} = payload.
- */
- DOWNLOAD_COMPLETE,
-
- /**
- * Arguments: {0} = event. {1} = artifact name. {2} = result.
- */
- EVENT_PUBLISHED,
-
- /**
- * Arguments: {0} = artifact name. {1} = artifact type.
- */
- UNSUPPORTED_ARTIFACT_TYPE;
-
- /**
- * Load message bundle (ModelLoaderMsgs.properties file)
- */
- static {
- EELFResourceManager.loadMessageBundle("org/onap/aai/modelloader/service/ModelLoaderMsgs");
- }
-
-}
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017-2018 European Software Marketing Ltd.
+ * ================================================================================
+ * 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=========================================================
+ */
+package org.onap.aai.modelloader.service;
+
+import com.att.eelf.i18n.EELFResourceManager;
+import org.onap.aai.cl.eelf.LogMessageEnum;
+
+public enum ModelLoaderMsgs implements LogMessageEnum {
+
+ /**
+ * Arguments: None.
+ */
+ LOADING_CONFIGURATION,
+
+ /**
+ * Arguments: None.
+ */
+ STOPPING_CLIENT,
+
+ /**
+ * Arguments: {0} = message.
+ */
+ INITIALIZING,
+
+ /**
+ * Arguments: {0} = reason.
+ */
+ ASDC_CONNECTION_ERROR,
+
+ /**
+ * Arguments: {0} = message.
+ */
+ DISTRIBUTION_EVENT,
+
+ /**
+ * Arguments: {0} = error message.
+ */
+ DISTRIBUTION_EVENT_ERROR,
+
+ /**
+ * Arguments: {0} = request type. {1} = endpoint. {2} = result code.
+ */
+ AAI_REST_REQUEST_SUCCESS,
+
+ /**
+ * Arguments: {0} = request type. {1} = endpoint. {2} = result code. {3} = result. message
+ */
+ AAI_REST_REQUEST_UNSUCCESSFUL,
+
+ /**
+ * Arguments: {0} = request type. {1} = endpoint. {2} = error message.
+ */
+ AAI_REST_REQUEST_ERROR,
+
+ /**
+ * Arguments: {0} = request type. {1} = endpoint. {2} = error message.
+ */
+ BABEL_REST_REQUEST_ERROR,
+
+ /**
+ * Arguments: {0} = info request payload.
+ **/
+ AAI_REST_REQUEST_PAYLOAD,
+
+ /**
+ * Arguments: {0} = artifact name
+ */
+ ARTIFACT_PARSE_ERROR,
+
+ /**
+ * Arguments: {0} = info request payload.
+ **/
+ BABEL_REST_REQUEST_PAYLOAD,
+
+ /**
+ * Arguments: {0} = info Babel response payload.
+ **/
+ BABEL_RESPONSE_PAYLOAD,
+
+ /**
+ * Arguments: {0} = artifact name. {1} = payload.
+ */
+ DOWNLOAD_COMPLETE,
+
+ /**
+ * Arguments: {0} = event. {1} = artifact name. {2} = result.
+ */
+ EVENT_PUBLISHED,
+
+ /**
+ * Arguments: {0} = artifact name. {1} = artifact type.
+ */
+ UNSUPPORTED_ARTIFACT_TYPE,
+
+ /**
+ * Arguments: {0} = artifact name.
+ */
+ DUPLICATE_VNFC_DATA_ERROR;
+
+ /**
+ * Load message bundle (ModelLoaderMsgs.properties file)
+ */
+ static {
+ EELFResourceManager.loadMessageBundle("org/onap/aai/modelloader/service/ModelLoaderMsgs");
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java b/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java
index 87cfdcc..84218e5 100644
--- a/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java
+++ b/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java
@@ -42,11 +42,11 @@ public final class JsonXmlConverter {
try {
new JSONObject(text);
isValid = true;
- } catch (JSONException ex) {
+ } catch (JSONException ex) { // NOSONAR
try {
new JSONArray(text);
isValid = true;
- } catch (JSONException ex1) {
+ } catch (JSONException ex1) { // NOSONAR
isValid = false;
}
}
diff --git a/src/main/resources/org/onap/aai/modelloader/service/ModelLoaderMsgs.properties b/src/main/resources/org/onap/aai/modelloader/service/ModelLoaderMsgs.properties
index 1e5658c..d337915 100644
--- a/src/main/resources/org/onap/aai/modelloader/service/ModelLoaderMsgs.properties
+++ b/src/main/resources/org/onap/aai/modelloader/service/ModelLoaderMsgs.properties
@@ -129,6 +129,12 @@ BABEL_REST_REQUEST_ERROR=\
Failed to send {0} request to {1}: {2}|\
Check configuration. Check network connection to Babel.|\
A failure occurred attempting to send a request to the Babel|\
+
+DUPLICATE_VNFC_DATA_ERROR=\
+ MDLSVC2006E|\
+ Artifact: {0} contains both TOSCA and XML VNF Catalog data.|\
+ Check artifact. |\
+ A failure occurred attempting to process VNF Catalog data in artifact from SDC|\
# DEBUG Level Logs
INITIALIZING=\