diff options
Diffstat (limited to 'src/main/java')
45 files changed, 3694 insertions, 2349 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 58e2bad..692f412 100644 --- a/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java +++ b/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java @@ -20,58 +20,66 @@ */ package org.onap.aai.modelloader.config; -import org.eclipse.jetty.util.security.Password; -import org.openecomp.sdc.api.consumer.IConfiguration; - +import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Properties; +import org.eclipse.jetty.util.security.Password; +import org.openecomp.sdc.api.consumer.IConfiguration; +/** + * Properties for the Model Loader + * + */ public class ModelLoaderConfig implements IConfiguration { - + // Configuration file structure public static final String PREFIX_MODEL_LOADER_CONFIG = "ml"; - public static final String PREFIX_DISTRIBUTION_CLIENT = - PREFIX_MODEL_LOADER_CONFIG + ".distribution."; + public static final String PREFIX_DISTRIBUTION_CLIENT = PREFIX_MODEL_LOADER_CONFIG + ".distribution."; public static final String PREFIX_AAI = PREFIX_MODEL_LOADER_CONFIG + ".aai."; + public static final String PREFIX_BABEL = PREFIX_MODEL_LOADER_CONFIG + ".babel."; public static final String PREFIX_DEBUG = PREFIX_MODEL_LOADER_CONFIG + ".debug."; + private static final String SUFFIX_KEYSTORE_FILE = "KEYSTORE_FILE"; + private static final String SUFFIX_KEYSTORE_PASS = "KEYSTORE_PASSWORD"; + // Configuration file properties - protected static final String PROP_ML_DISTRIBUTION_ACTIVE_SERVER_TLS_AUTH = + 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_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 - + "KEYSTORE_PASSWORD"; - protected static final String PROP_ML_DISTRIBUTION_KEYSTORE_FILE = PREFIX_DISTRIBUTION_CLIENT - + "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_TIMEOUT = PREFIX_DISTRIBUTION_CLIENT - + "POLLING_TIMEOUT"; + 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_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_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_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"; + 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 + "KEYSTORE_FILE"; - protected static final String PROP_AAI_KEYSTORE_PASSWORD = PREFIX_AAI + "KEYSTORE_PASSWORD"; + protected static final String PROP_AAI_KEYSTORE_FILE = PREFIX_AAI + SUFFIX_KEYSTORE_FILE; + protected static final String PROP_AAI_KEYSTORE_PASSWORD = PREFIX_AAI + SUFFIX_KEYSTORE_PASS; protected static final String PROP_AAI_MODEL_RESOURCE_URL = PREFIX_AAI + "MODEL_URL"; protected static final String PROP_AAI_NAMED_QUERY_RESOURCE_URL = PREFIX_AAI + "NAMED_QUERY_URL"; protected static final String PROP_AAI_VNF_IMAGE_RESOURCE_URL = PREFIX_AAI + "VNF_IMAGE_URL"; protected static final String PROP_AAI_AUTHENTICATION_USER = PREFIX_AAI + "AUTH_USER"; protected static final String PROP_AAI_AUTHENTICATION_PASSWORD = PREFIX_AAI + "AUTH_PASSWORD"; + protected static final String PROP_BABEL_BASE_URL = PREFIX_BABEL + "BASE_URL"; + protected static final String PROP_BABEL_KEYSTORE_FILE = PREFIX_BABEL + SUFFIX_KEYSTORE_FILE; + protected static final String PROP_BABEL_KEYSTORE_PASSWORD = PREFIX_BABEL + SUFFIX_KEYSTORE_PASS; + 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 Properties modelLoaderProperties = null; @@ -80,6 +88,11 @@ public class ModelLoaderConfig implements IConfiguration { private List<String> artifactTypes = null; + private List<String> msgBusAddrs = null; + + private String modelVersion = null; + + /** * This is the class constructor. * @@ -91,14 +104,22 @@ public class ModelLoaderConfig implements IConfiguration { this.certLocation = certLocation; // Get list of artifacts - artifactTypes = new ArrayList<String>(); + artifactTypes = new ArrayList<>(); if (modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ARTIFACT_TYPES) != null) { - String[] artTypeList = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ARTIFACT_TYPES) - .split(","); + String[] artTypeList = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ARTIFACT_TYPES).split(","); for (String artType : artTypeList) { artifactTypes.add(artType); } } + + // Get list of message bus addresses + msgBusAddrs = new ArrayList<>(); + if (modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_MSG_BUS_ADDRESSES) != null) { + String[] msgBusList = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_MSG_BUS_ADDRESSES).split(","); + for (String addr : msgBusList) { + msgBusAddrs.add(addr); + } + } } @Override @@ -129,8 +150,7 @@ public class ModelLoaderConfig implements IConfiguration { @Override public String getKeyStorePassword() { - return Password - .deobfuscate(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_KEYSTORE_PASSWORD)); + return Password.deobfuscate(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_KEYSTORE_PASSWORD)); } @Override @@ -145,14 +165,12 @@ public class ModelLoaderConfig implements IConfiguration { @Override public int getPollingInterval() { - return Integer - .parseInt(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_POLLING_INTERVAL)); + return Integer.parseInt(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_POLLING_INTERVAL)); } @Override public int getPollingTimeout() { - return Integer - .parseInt(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_POLLING_TIMEOUT)); + return Integer.parseInt(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_POLLING_TIMEOUT)); } @Override @@ -167,53 +185,81 @@ public class ModelLoaderConfig implements IConfiguration { @Override public boolean isFilterInEmptyResources() { - return false; + return false; } @Override public Boolean isUseHttpsWithDmaap() { - String useHTTPS = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_HTTPS_WITH_DMAAP); - return useHTTPS == null ? false : Boolean.valueOf(useHTTPS); + String useHTTPS = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_HTTPS_WITH_DMAAP); + return useHTTPS == null ? false : Boolean.valueOf(useHTTPS); } - + + @Override + public List<String> getMsgBusAddress() { + return msgBusAddrs; + } + public String getAaiKeyStorePath() { - return certLocation + "/" + modelLoaderProperties.getProperty(PROP_AAI_KEYSTORE_FILE); + return certLocation + File.separator + modelLoaderProperties.getProperty(PROP_AAI_KEYSTORE_FILE); + } + + public String getBabelKeyStorePath() { + return certLocation + File.separator + modelLoaderProperties.getProperty(PROP_BABEL_KEYSTORE_FILE); } public String getAaiKeyStorePassword() { return Password.deobfuscate(modelLoaderProperties.getProperty(PROP_AAI_KEYSTORE_PASSWORD)); } + public String getBabelKeyStorePassword() { + return Password.deobfuscate(modelLoaderProperties.getProperty(PROP_BABEL_KEYSTORE_PASSWORD)); + } + public String getAaiBaseUrl() { return modelLoaderProperties.getProperty(PROP_AAI_BASE_URL); } + public String getBabelBaseUrl() { + return modelLoaderProperties.getProperty(PROP_BABEL_BASE_URL); + } + + public String getBabelGenerateArtifactsUrl() { + return modelLoaderProperties.getProperty(PROP_BABEL_GENERATE_RESOURCE_URL); + } + public String getAaiModelUrl(String version) { - return modelLoaderProperties.getProperty(PROP_AAI_MODEL_RESOURCE_URL).replace("v*", version); + setModelVersion(version); + return updatePropertyOXMVersion(modelLoaderProperties, PROP_AAI_MODEL_RESOURCE_URL, version); } public String getAaiNamedQueryUrl(String version) { - return modelLoaderProperties.getProperty(PROP_AAI_NAMED_QUERY_RESOURCE_URL).replace("v*", version); + return updatePropertyOXMVersion(modelLoaderProperties, PROP_AAI_NAMED_QUERY_RESOURCE_URL, version); } public String getAaiVnfImageUrl() { - return modelLoaderProperties.getProperty(PROP_AAI_VNF_IMAGE_RESOURCE_URL); + return updatePropertyOXMVersion(modelLoaderProperties, PROP_AAI_VNF_IMAGE_RESOURCE_URL, getModelVersion()); } public String getAaiAuthenticationUser() { return modelLoaderProperties.getProperty(PROP_AAI_AUTHENTICATION_USER); } + public String getModelVersion() { + return modelVersion; + } + + public void setModelVersion(String modelVersion) { + this.modelVersion = modelVersion; + } + /** - * @return password for AAI authentication that has been reverse-engineered - * from its obfuscated form. + * @return password for AAI authentication that has been reverse-engineered from its obfuscated form. */ public String getAaiAuthenticationPassword() { - String password = Password - .deobfuscate(modelLoaderProperties.getProperty(PROP_AAI_AUTHENTICATION_PASSWORD)); + String password = Password.deobfuscate(modelLoaderProperties.getProperty(PROP_AAI_AUTHENTICATION_PASSWORD)); - if ((password != null) && (password.equals(""))) { - return null; + if (password != null && password.isEmpty()) { + password = null; } return password; @@ -224,16 +270,30 @@ public class ModelLoaderConfig implements IConfiguration { */ public boolean getIngestSimulatorEnabled() { String propValue = modelLoaderProperties.getProperty(PROP_DEBUG_INGEST_SIMULATOR); + return propValue != null && "enabled".equalsIgnoreCase(propValue); + } - if (propValue == null) { - return false; - } - - if (propValue.compareToIgnoreCase("enabled") == 0) { - return true; - } - - return false; + /** + * @return a String value of the defined property with the oxm version + */ + private String updatePropertyOXMVersion(Properties modelLoaderProperties, String propertyName, String version) { + if (version != null) + return modelLoaderProperties.getProperty(propertyName).replace("v*", version); + else + return modelLoaderProperties.getProperty(propertyName); } + + + + /** + * @return a boolean value indicating whether model loader is connected to ASDC. + */ + public boolean getASDCConnectionDisabled(){ + String propValue = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ASDC_CONNECTION_DISABLED); + return propValue != null && "true".equalsIgnoreCase(propValue); + + } + + } diff --git a/src/main/java/org/onap/aai/modelloader/entity/Artifact.java b/src/main/java/org/onap/aai/modelloader/entity/Artifact.java index 32a13b7..4c0e0f1 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/Artifact.java +++ b/src/main/java/org/onap/aai/modelloader/entity/Artifact.java @@ -22,23 +22,23 @@ package org.onap.aai.modelloader.entity; public abstract class Artifact { - private String payload; - private ArtifactType type; + private String payload; + private ArtifactType type; - public Artifact(ArtifactType type) { - this.type = type; - } - - public ArtifactType getType() { - return type; - } + public Artifact(ArtifactType type) { + this.type = type; + } - public String getPayload() { - return payload; - } + public ArtifactType getType() { + return type; + } - public void setPayload(String payload) { - this.payload = payload; - } + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } } diff --git a/src/main/java/org/onap/aai/modelloader/entity/ArtifactHandler.java b/src/main/java/org/onap/aai/modelloader/entity/ArtifactHandler.java index 44335b8..9e80e05 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/ArtifactHandler.java +++ b/src/main/java/org/onap/aai/modelloader/entity/ArtifactHandler.java @@ -23,15 +23,19 @@ package org.onap.aai.modelloader.entity; import java.util.List;
import org.onap.aai.modelloader.config.ModelLoaderConfig;
+import org.onap.aai.modelloader.restclient.AaiRestClient;
public abstract class ArtifactHandler {
- protected ModelLoaderConfig config;
+ protected ModelLoaderConfig config;
- public ArtifactHandler(ModelLoaderConfig config) {
- this.config = config;
- }
+ public ArtifactHandler(ModelLoaderConfig config) {
+ this.config = config;
+ }
- public abstract boolean pushArtifacts(List<Artifact> artifacts, String distributionId);
+ public abstract boolean pushArtifacts(List<Artifact> artifacts, String distributionId, List<Artifact> completedArtifacts,
+ AaiRestClient restClient);
+ public abstract void rollback(List<Artifact> completedArtifacts, String distributionId,
+ AaiRestClient aaiClient);
}
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 1a71004..6959936 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/ArtifactType.java +++ b/src/main/java/org/onap/aai/modelloader/entity/ArtifactType.java @@ -21,8 +21,8 @@ package org.onap.aai.modelloader.entity; public enum ArtifactType { - MODEL, - MODEL_V8, - NAMED_QUERY, - VNF_CATALOG; + MODEL, + MODEL_V8, + NAMED_QUERY, + VNF_CATALOG; } 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 c5b6447..3219625 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 @@ -24,8 +24,9 @@ import org.onap.aai.modelloader.entity.Artifact; import org.onap.aai.modelloader.entity.ArtifactType; public class VnfCatalogArtifact extends Artifact { - public VnfCatalogArtifact(String payload) { - super(ArtifactType.VNF_CATALOG); - setPayload(payload); - } + + public VnfCatalogArtifact(String payload) { + super(ArtifactType.VNF_CATALOG); + 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 9022516..b224407 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 @@ -20,171 +20,159 @@ */
package org.onap.aai.modelloader.entity.catalog;
-import com.sun.jersey.api.client.ClientResponse;
-
-import generated.VnfCatalog;
-import generated.VnfCatalog.PartNumberList;
-
-import inventory.aai.openecomp.org.v8.VnfImage;
-
-import org.eclipse.persistence.jaxb.MarshallerProperties;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import java.io.UnsupportedEncodingException;
+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 org.apache.commons.text.StringEscapeUtils;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
import org.onap.aai.modelloader.config.ModelLoaderConfig;
import org.onap.aai.modelloader.entity.Artifact;
import org.onap.aai.modelloader.entity.ArtifactHandler;
import org.onap.aai.modelloader.restclient.AaiRestClient;
-import org.onap.aai.modelloader.restclient.AaiRestClient.MimeType;
import org.onap.aai.modelloader.service.ModelLoaderMsgs;
-import org.onap.aai.cl.api.Logger;
-import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.aai.restclient.client.OperationResult;
import org.springframework.web.util.UriUtils;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import javax.ws.rs.core.Response;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.Unmarshaller;
-
-
+/**
+ * VNF Catalog specific handling
+ */
public class VnfCatalogArtifactHandler extends ArtifactHandler {
- private static Logger logger = LoggerFactory.getInstance()
- .getLogger(VnfCatalogArtifactHandler.class.getName());
-
- public VnfCatalogArtifactHandler(ModelLoaderConfig config) {
- super(config);
- }
+ private static Logger logger = LoggerFactory.getInstance().getLogger(VnfCatalogArtifactHandler.class.getName());
- @Override
- public boolean pushArtifacts(List<Artifact> artifacts, String distributionId) {
- for (Artifact art : artifacts) {
- VnfCatalogArtifact vnfCatalog = (VnfCatalogArtifact) art;
- String artifactPayload = vnfCatalog.getPayload();
+ public static final String ATTR_UUID = "uuid";
- AaiRestClient restClient = new AaiRestClient(this.config);
- List<VnfImage> putImages = new ArrayList<VnfImage>();
-
- try {
- JAXBContext inputContext = JAXBContext.newInstance(VnfCatalog.class);
- Unmarshaller unmarshaller = inputContext.createUnmarshaller();
- StringReader reader = new StringReader(artifactPayload);
- VnfCatalog cat = (VnfCatalog) unmarshaller.unmarshal(reader);
+ public VnfCatalogArtifactHandler(ModelLoaderConfig config) {
+ super(config);
+ }
- int numParts = cat.getPartNumberList().size();
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.modelloader.entity.ArtifactHandler#pushArtifacts(java.util.List, java.lang.String)
+ */
+ @Override
+ public boolean pushArtifacts(List<Artifact> artifacts, String distributionId, List<Artifact> completedArtifacts,
+ AaiRestClient aaiClient) {
+ for (Artifact artifact : artifacts) {
+ try {
+ distributeVnfcData(aaiClient, distributionId, artifact, completedArtifacts);
+ } catch (VnfImageException e) {
+ if (e.getResultCode().isPresent()) {
+ logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,
+ "Ingestion failed on vnf-image " + e.getImageId() + " with status "
+ + e.getResultCode().orElse(0) + ". Rolling back distribution.");
+ } else {
+ logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,
+ "Ingestion failed on " + e.getImageId() + ". Rolling back distribution.");
+ }
+ return false;
+ }
+ }
- for (int i = 0; i < numParts; i++) {
+ return true;
+ }
- PartNumberList pnl = cat.getPartNumberList().get(i);
+ private void distributeVnfcData(AaiRestClient restClient, String distributionId, Artifact vnfcArtifact,
+ List<Artifact> completedArtifacts) throws VnfImageException {
- String application = pnl.getVendorInfo().getVendorModel();
- String applicationVendor = pnl.getVendorInfo().getVendorName();
+ List<Map<String, String>> vnfcData = unmarshallVnfcData(vnfcArtifact);
- int numVersions = pnl.getSoftwareVersionList().size();
+ for (Map<String, String> dataItem : vnfcData) {
+ // If an empty dataItem is supplied, do nothing.
+ if (dataItem.isEmpty()) {
+ logger.warn(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Empty image data supplied, skipping ingestion.");
+ return;
+ }
- for (int j = 0; j < numVersions; j++) {
- String applicationVersion = pnl.getSoftwareVersionList().get(j).getSoftwareVersion();
+ String urlParams;
+ StringBuilder imageId = new StringBuilder("vnf image");
- String imageId = "vnf image " + applicationVendor + " " + application + " "
- + applicationVersion;
+ try {
+ urlParams = buildUrlImgIdStrings(imageId, dataItem);
+ } catch (UnsupportedEncodingException e) {
+ throw new VnfImageException(e);
+ }
- String queryURI = "application-vendor=" + applicationVendor + "&application=" + application + "&application-version=" + applicationVersion;
-
- String getUrl = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "?" + UriUtils.encodePath(queryURI, "UTF-8");
+ OperationResult tryGet =
+ restClient.getResource(config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "?" + urlParams,
+ distributionId, MediaType.APPLICATION_JSON_TYPE);
- ClientResponse tryGet = restClient.getResource(getUrl, distributionId, MimeType.JSON);
if (tryGet == null) {
- logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,
- "Ingestion failed on " + imageId + ". Rolling back distribution.");
- failureCleanup(putImages, restClient, distributionId);
- return false;
+ throw new VnfImageException(imageId.toString());
}
- if (tryGet.getStatus() == Response.Status.NOT_FOUND.getStatusCode()) {
- // this vnf-image not already in the db, need to add
- // only do this on 404 bc other error responses could mean there
- // are problems that
- // you might not want to try to PUT against
-
- VnfImage image = new VnfImage();
- image.setApplication(application);
- image.setApplicationVendor(applicationVendor);
- image.setApplicationVersion(applicationVersion);
- String uuid = UUID.randomUUID().toString();
- image.setUuid(uuid); // need to create uuid
-
- System.setProperty("javax.xml.bind.context.factory",
- "org.eclipse.persistence.jaxb.JAXBContextFactory");
- JAXBContext jaxbContext = JAXBContext.newInstance(VnfImage.class);
- Marshaller marshaller = jaxbContext.createMarshaller();
- marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
- marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
- marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);
- StringWriter writer = new StringWriter();
- marshaller.marshal(image, writer);
- String payload = writer.toString();
-
- String putUrl = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/"
- + uuid;
-
- ClientResponse putResp = restClient.putResource(putUrl, payload, distributionId,
- MimeType.JSON);
- if (putResp == null
- || putResp.getStatus() != Response.Status.CREATED.getStatusCode()) {
- logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,
- "Ingestion failed on vnf-image " + imageId + ". Rolling back distribution.");
- failureCleanup(putImages, restClient, distributionId);
- return false;
- }
- putImages.add(image);
- logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, imageId + " successfully ingested.");
- } else if (tryGet.getStatus() == Response.Status.OK.getStatusCode()) {
- logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT,
- imageId + " already exists. Skipping ingestion.");
+
+ 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());
+ }
+ 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
- logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,
- "Ingestion failed on vnf-image " + imageId + " with status " + tryGet.getStatus()
- + ". Rolling back distribution.");
- failureCleanup(putImages, restClient, distributionId);
- return false;
+ // if other than 404 or 200, something went wrong
+ throw new VnfImageException(imageId.toString(), resultCode);
}
- }
}
+ }
- } catch (JAXBException e) {
- logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,
- "Ingestion failed. " + e.getMessage() + ". Rolling back distribution.");
- failureCleanup(putImages, restClient, distributionId);
- return false;
- } catch (UnsupportedEncodingException e) {
- logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed. " + e.getMessage() + ". Rolling back distribution.");
- failureCleanup(putImages, restClient, distributionId);
- return false;
- }
+ 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());
+ }
+ return urlParams.deleteCharAt(urlParams.length() - 1).toString();
+ }
+
+ private boolean putVnfImage(AaiRestClient restClient, Map<String, String> dataItem, String distributionId) {
+ // Generate a new UUID for the image data item
+ String uuid = UUID.randomUUID().toString();
+ dataItem.put(ATTR_UUID, uuid);
+
+ String payload = createVnfImagePayload(dataItem);
+ String putUrl = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/" + uuid;
+ OperationResult putResp =
+ restClient.putResource(putUrl, payload, distributionId, MediaType.APPLICATION_JSON_TYPE);
+ return putResp != null && putResp.getResultCode() == Response.Status.CREATED.getStatusCode();
+ }
+
+ private String createVnfImagePayload(Map<String, String> dataItem) {
+ dataItem.put(ATTR_UUID, UUID.randomUUID().toString());
+ return new Gson().toJson(dataItem);
+ }
+
+ private List<Map<String, String>> unmarshallVnfcData(Artifact vnfcArtifact) {
+ // Unmarshall Babel JSON payload into a List of Maps of JSON attribute name/values.
+ return new Gson().fromJson(StringEscapeUtils.unescapeJson(vnfcArtifact.getPayload()),
+ new TypeToken<List<Map<String, String>>>() {}.getType());
}
- return true;
- }
-
- /*
- * if something fails in the middle of ingesting the catalog we want to
- * rollback any changes to the db
- */
- private void failureCleanup(List<VnfImage> putImages, AaiRestClient restClient, String transId) {
- for (VnfImage image : putImages) {
- String url = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "/vnf-image/"
- + image.getUuid();
- restClient.getAndDeleteResource(url, transId); // try to delete the image,
- // if something goes wrong
- // we can't really do
- // anything here
+ /*
+ * 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) {
+ 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);
+ }
+ }
}
- }
}
diff --git a/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfImageException.java b/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfImageException.java new file mode 100644 index 0000000..9459c49 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfImageException.java @@ -0,0 +1,58 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.entity.catalog; + +import java.util.Optional; + +/** + * Exception class used by the VnfCatalogArtifactHandler + */ +class VnfImageException extends Exception { + + private static final long serialVersionUID = 1L; + + private final String imageId; + private final transient Optional<Integer> resultCode; + + public VnfImageException(String imageId) { + this.imageId = imageId; + this.resultCode = Optional.empty(); + } + + public VnfImageException(String imageId, int resultCode) { + this.imageId = imageId; + this.resultCode = Optional.of(resultCode); + } + + public VnfImageException(Exception e) { + this.imageId = e.getMessage(); + this.resultCode = Optional.empty(); + } + + public String getImageId() { + return imageId; + } + + public Optional<Integer> getResultCode() { + return resultCode; + } + +}
\ No newline at end of file diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/AbstractModelArtifact.java b/src/main/java/org/onap/aai/modelloader/entity/model/AbstractModelArtifact.java index 889db55..3c1152f 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/AbstractModelArtifact.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/AbstractModelArtifact.java @@ -29,55 +29,59 @@ import org.onap.aai.modelloader.entity.Artifact; import org.onap.aai.modelloader.entity.ArtifactType; import org.onap.aai.modelloader.restclient.AaiRestClient; -public abstract class AbstractModelArtifact extends Artifact { - - private String modelNamespace; - private String modelNamespaceVersion; - private Set<String> referencedModelIds = new HashSet<>(); - - public AbstractModelArtifact(ArtifactType type) { - super(type); - } - - public Set<String> getDependentModelIds() { - return referencedModelIds; - } - - public void addDependentModelId(String dependentModelId) { - this.referencedModelIds.add(dependentModelId); - } - - public String getModelNamespace() { - return modelNamespace; - } - - public void setModelNamespace(String modelNamespace) { - this.modelNamespace = modelNamespace; - - // Get the version from the namespace (in format 'http://org.openecomp.aai.inventory/v9') - String[] parts = modelNamespace.split("/"); - modelNamespaceVersion = parts[parts.length-1].trim(); - } - - public String getModelNamespaceVersion() { - return modelNamespaceVersion; - } - - public abstract String getUniqueIdentifier(); - - public abstract boolean push(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, List<AbstractModelArtifact> addedModels); - - public abstract void rollbackModel(AaiRestClient aaiClient, ModelLoaderConfig config, String distId); +public abstract class AbstractModelArtifact extends Artifact implements IModelArtifact { + + private String modelNamespace; + private String modelNamespaceVersion; + private Set<String> referencedModelIds = new HashSet<>(); + + public AbstractModelArtifact(ArtifactType type) { + super(type); + } + + public Set<String> getDependentModelIds() { + return referencedModelIds; + } + + @Override + public void addDependentModelId(String dependentModelId) { + this.referencedModelIds.add(dependentModelId); + } + + public String getModelNamespace() { + return modelNamespace; + } + + @Override + public void setModelNamespace(String modelNamespace) { + this.modelNamespace = modelNamespace; + + // Get the version from the namespace (in format 'http://org.openecomp.aai.inventory/v9') + String[] parts = modelNamespace.split("/"); + modelNamespaceVersion = parts[parts.length - 1].trim(); + } + + public String getModelNamespaceVersion() { + return modelNamespaceVersion; + } + + public abstract String getUniqueIdentifier(); + + public abstract boolean push(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, + List<Artifact> completedArtifacts); + + public abstract void rollbackModel(AaiRestClient aaiClient, ModelLoaderConfig config, String distId); + @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("\nType=" + getType().toString() +"\nId=" + getUniqueIdentifier() +"\nVersion=" + getModelNamespaceVersion() + "\nDependant models: "); - for (String dep : referencedModelIds) { - sb.append(dep + " "); - } - - return sb.toString(); - } - - + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("\nType=" + getType().toString() + "\nId=" + getUniqueIdentifier() + "\nVersion=" + + getModelNamespaceVersion() + "\nDependant models: "); + for (String dep : referencedModelIds) { + sb.append(dep + " "); + } + + return sb.toString(); + } + } diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/AbstractModelArtifactParser.java b/src/main/java/org/onap/aai/modelloader/entity/model/AbstractModelArtifactParser.java new file mode 100644 index 0000000..fd6af31 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/entity/model/AbstractModelArtifactParser.java @@ -0,0 +1,293 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.entity.model; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.BiConsumer; +import java.util.stream.Collector; +import java.util.stream.IntStream; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +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.service.ModelLoaderMsgs; + +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; + +/** + * This class provides common behaviour for implementations of IModelParser. + * + * Some of the common behaviour takes the form of abstract methods that will be implemented in concrete classes. + * + * Some other behaviour will be overridden in concrete classes. + */ +public abstract class AbstractModelArtifactParser implements IModelParser { + private static Logger logger = LoggerFactory.getInstance().getLogger(AbstractModelArtifactParser.class); + + protected static final String RELATIONSHIP_DATA = "relationship-data"; + private static final String RELATIONSHIP_KEY = "relationship-key"; + private static final String RELATIONSHIP_VALUE = "relationship-value"; + + BiConsumer<Pair<String, String>, Node> applyRelationshipValue = (p, n) -> { + if (n.getNodeName().equalsIgnoreCase(RELATIONSHIP_KEY)) { + p.setKey(n.getTextContent().trim()); + } else { + p.setValue(n.getTextContent().trim()); + } + }; + + + /** + * This method is responsible for parsing the payload to produce a list of artifacts. + * + * @param artifactPayload the payload to be parsed + * @param artifactName the name of the artifact to be parsed + * @return List<Artifact> a list of artifacts that have been parsed from the payload. + */ + @Override + public List<Artifact> parse(String artifactPayload, String artifactName) { + List<Artifact> modelList = 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(artifactPayload)); + Document doc = builder.parse(is); + + IModelArtifact model = parseModel(doc.getDocumentElement(), artifactPayload); + + if (!processParsedModel(modelList, artifactName, model)) { + modelList = null; + } + } catch (Exception ex) { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, + buildArtifactParseExceptionMessage(artifactName, ex.getLocalizedMessage())); + } + + return modelList; + } + + private IModelArtifact parseModel(Node modelNode, String payload) { + IModelArtifact model = createModelArtifactInstance(); + model.setPayload(payload); + + Element e = (Element) modelNode; + model.setModelNamespace(e.getAttribute("xmlns")); + + parseNode(modelNode, model); + + return modelIsValid(model) ? model : null; + } + + /** + * This method is responsible for creating a new instance of IModel that represents the model id for a concrete + * implementation of IArtifactParser. + * + * @return IModelArtifact implementation of IModel that represents the model id for a concrete implementation of + * IArtifactParser + */ + abstract IModelArtifact createModelArtifactInstance(); + + /** + * This method is responsible for the actual parsing of a node. + * + * It will do one of three things: + * <ol> + * <li>set the version id if the name of the node is the same as the name of the node that is the version Id</li> + * <li>if the node is contains data about the relationship it will parse the node accordingly</li> + * <li>if it does neither of option 1 or 2 it will parse the children of this node</li> + * </ol> + * + * @param node node to be parsed + * @param model the model artifact to be updated with either the versionId or details of dependent node + */ + void parseNode(Node node, IModelArtifact model) { + if (node.getNodeName().equalsIgnoreCase(getVersionIdNodeName())) { + setVersionId(model, node); + } else if (node.getNodeName().equalsIgnoreCase(RELATIONSHIP_DATA)) { + parseRelationshipNode(node, model); + } else { + parseChildNodes(node, model); + } + } + + /** + * This method gets the name of the node that acts as the version Id for the node. + * + * @return String name of the node that acts as the version Id for the node + */ + abstract String getVersionIdNodeName(); + + /** + * This method is responsible for setting the values on the model artifact that represent the version Id. Each + * implementation of a IModelArtifact has its own properties that define the version Id. + * + * @param model the model artifact upon which the version Id will be set + * @param node the source of the data that holds the actual value of the version id to be set on the model artifact + */ + abstract void setVersionId(IModelArtifact model, Node node); + + /** + * @param relationshipNode a node containing child nodes storing relationship data + * @param model artifact whose dependent node id will be update with any relationship data if it exists + */ + void parseRelationshipNode(Node relationshipNode, IModelArtifact model) { + NodeList nodeList = getChildNodes(relationshipNode); + + IModelId modelId = buildModelId(nodeList); + + updateModelsDependentNodeId(model, modelId); + } + + private NodeList getChildNodes(Node relationshipNode) { + Objects.requireNonNull(relationshipNode); + NodeList nodeList = relationshipNode.getChildNodes(); + Objects.requireNonNull(nodeList); + + return nodeList; + } + + /** + * This method is responsible for building an instance of IModelId representing the id of the model. + * + * @param nodeList list of modes used to build the model id. + * @return IModelId instance of IModelId representing the id of the model + */ + IModelId buildModelId(NodeList nodeList) { + Pair<String, String> relationship = IntStream.range(0, nodeList.getLength()).mapToObj(nodeList::item) // + .filter(this::filterRelationshipNode) + .collect(Collector.of(Pair::new, applyRelationshipValue, (p, n) -> p)); + + IModelId modelId = createModelIdInstance(); + modelId.setRelationship(relationship); + + return modelId; + } + + /** + * This method tests if a node is either one that either represents a relationship key or a relationship value. + * + * @param n the node to to be tested + * @return <code>true</code> if the node is either represents a relationship key or a relationship value + */ + boolean filterRelationshipNode(Node n) { + return n.getNodeName().equalsIgnoreCase(RELATIONSHIP_KEY) + || n.getNodeName().equalsIgnoreCase(RELATIONSHIP_VALUE); + } + + /** + * This method is responsible for creating an instance of {@link AbstractModelArtifactParser.ModelId} + * + * @return IModelId instance of {@link AbstractModelArtifactParser.ModelId} + */ + IModelId createModelIdInstance() { + return new ModelId(); + } + + private void updateModelsDependentNodeId(IModelArtifact model, IModelId modelId) { + if (modelId.defined()) { + model.addDependentModelId(modelId.toString()); + } + } + + /** + * This method is responsible for parsing the children of a given node. + * + * @param node node whose children, if any, should be parsed. + * @param model model to be updated as a result of parsing the node + */ + void parseChildNodes(Node node, IModelArtifact model) { + NodeList nodeList = node.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node childNode = nodeList.item(i); + parseNode(childNode, model); + } + } + + /** + * Validates if the mode is valid or not by examining specific properties of the model. + * + * @param model model to be validated + * @return <code>true</code> if the mode is valid otherwise <code>false</code> + */ + abstract boolean modelIsValid(IModelArtifact model); + + /** + * This method is responsible for building a message used for logging artifact parsing errors. + * + * @param artifactName the name of the artifact + * @param localisedMessage the message associated with the exception that is raised by the error + * @return String a message used for logging artifact parsing errors + */ + abstract String buildArtifactParseExceptionMessage(String artifactName, String localisedMessage); + + /** + * This method is responsible for either adding the model artifact to the list of model artifacts or reporting an + * error. + * + * If the model is not null then it will be added to the list of artifacts otherwise an error will be logged. + * + * @param modelList the list of artifacts to which the model will be added if it is not null + * @param artifactName the name of the artifact + * @param artifactModel the model artifact to be added to the list of model artifacts + * @return <code>true/code> if the model is not null otherwise <code>false</code> + */ + abstract boolean processParsedModel(List<Artifact> modelList, String artifactName, IModelArtifact artifactModel); + + private class ModelId implements IModelId { + private String modelIdValue; + + @Override + public void setRelationship(Pair<String, String> p) { + if (getModelElementRelationshipKey().equals(p.getKey())) { + modelIdValue = p.getValue(); + } + } + + @Override + public boolean defined() { + return modelIdValue != null; + } + + @Override + public String toString() { + return modelIdValue; + } + } + + /** + * This method gets the name of the key of the element relationship for the model. + * + * @return String name of the key of the element relationship for the model + */ + abstract String getModelElementRelationshipKey(); +} diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/BabelArtifactParsingException.java b/src/main/java/org/onap/aai/modelloader/entity/model/BabelArtifactParsingException.java new file mode 100644 index 0000000..1426e82 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/entity/model/BabelArtifactParsingException.java @@ -0,0 +1,49 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.entity.model; + +/** + * This class represents an exception encountered when parsing an XML model Artifact. + */ +public class BabelArtifactParsingException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + public BabelArtifactParsingException(String message) { + super(message); + } + + /** + * Constructor for an instance of this exception with a message and actual exception encountered. + * + * @param message information about the exception + * @param cause the actual exception that was encountered + */ + public BabelArtifactParsingException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/IModelArtifact.java b/src/main/java/org/onap/aai/modelloader/entity/model/IModelArtifact.java new file mode 100644 index 0000000..5978b99 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/entity/model/IModelArtifact.java @@ -0,0 +1,51 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.entity.model; + +/** + * Defines methods for implementations of a Model Artifact. + */ +public interface IModelArtifact { + + /** + * This method is responsible for adding the id of a dependent node to the model. + * + * The model will have a collection of dependent nodes that may or may not have contents. + * + * @param value id of a dependent node to be added to the model. + */ + void addDependentModelId(String value); + + /** + * This method sets the payload for the model. + * + * @param payload the actual payload for the model + */ + void setPayload(String payload); + + /** + * This methods sets the value of the namespace for the model. + * + * @param xmlns the namespace for the model + */ + void setModelNamespace(String xmlns); +} diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/IModelId.java b/src/main/java/org/onap/aai/modelloader/entity/model/IModelId.java new file mode 100644 index 0000000..9b635bf --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/entity/model/IModelId.java @@ -0,0 +1,51 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.entity.model; + +/** + * Defines methods for c + */ +public interface IModelId { + + /** + * This method is responsible for using the values in the supplied Pair to set the id of the model. + * + * The definition of what the relationship will be is defined by the implementation. Some model ids would have + * single key/value pairs, others would have a composite key. + * + * Where the id of the model is a composite key multiple calls to this method will be required to successfully set + * the relationship in order to meet the rules of {@link #defined} + * + * @param pair object representing a key and its value. + */ + void setRelationship(Pair<String, String> pair); + + /** + * This method indicates whether the id of the model has been defined according to the rules of the specific model + * implemented. + * + * Usually defined means that all properties that make up the key have been set. + * + * @return boolean <code>true</code> if the id of the model has been defined otherwise <code>false</code> + */ + boolean defined(); +} diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/IModelParser.java b/src/main/java/org/onap/aai/modelloader/entity/model/IModelParser.java index bf2361b..758a882 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/IModelParser.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/IModelParser.java @@ -26,5 +26,6 @@ import org.onap.aai.modelloader.entity.Artifact; @FunctionalInterface public interface IModelParser { - public List<Artifact> parse(byte[] artifactPayload, String artifactName); + + List<Artifact> parse(String artifactPayload, String artifactName); } diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifact.java b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifact.java index d15776a..896167a 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifact.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifact.java @@ -22,8 +22,9 @@ package org.onap.aai.modelloader.entity.model; import java.io.StringWriter; import java.util.List; - +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.xml.XMLConstants; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; @@ -37,172 +38,222 @@ import org.onap.aai.modelloader.restclient.AaiRestClient; import org.onap.aai.modelloader.service.ModelLoaderMsgs; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; -import org.w3c.dom.Node; +import org.onap.aai.modelloader.entity.Artifact; +import org.onap.aai.restclient.client.OperationResult; -import com.sun.jersey.api.client.ClientResponse; +import org.w3c.dom.Node; public class ModelArtifact extends AbstractModelArtifact { - private static final String AAI_MODEL_VER_SUB_URL = "/model-vers/model-ver"; - - private static Logger logger = LoggerFactory.getInstance().getLogger(ModelArtifact.class.getName()); - - private String modelVerId; - private String modelInvariantId; - private Node modelVer; - private boolean firstVersionOfModel = false; - - public ModelArtifact() { - super(ArtifactType.MODEL); - } - - public String getModelVerId() { - return modelVerId; - } - - public void setModelVerId(String modelVerId) { - this.modelVerId = modelVerId; - } - - public String getModelInvariantId() { - return modelInvariantId; - } - - public void setModelInvariantId(String modelInvariantId) { - this.modelInvariantId = modelInvariantId; - } - - public Node getModelVer() { - return modelVer; - } - - public void setModelVer(Node modelVer) { - this.modelVer = modelVer; - } - - @Override - public String getUniqueIdentifier() { - return getModelInvariantId() + "|" + getModelVerId(); - } - - @Override - public boolean push(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, List<AbstractModelArtifact> addedModels) { - ClientResponse getResponse = aaiClient.getResource(getModelUrl(config), distId, AaiRestClient.MimeType.XML); - if ( (getResponse == null) || (getResponse.getStatus() != Response.Status.OK.getStatusCode()) ) { - // Only attempt the PUT if the model doesn't already exist - ClientResponse putResponse = aaiClient.putResource(getModelUrl(config), getPayload(), distId, AaiRestClient.MimeType.XML); - if ( (putResponse != null) && (putResponse.getStatus() == Response.Status.CREATED.getStatusCode()) ) { - addedModels.add(this); - - // Flag this as the first version of the model that has been added. - firstVersionOfModel = true; - - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getUniqueIdentifier() + " successfully ingested."); - } - else { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed for " + getType().toString() + " " + getUniqueIdentifier() + - ". Rolling back distribution."); - return false; - } - } - else { - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getModelInvariantId() + " already exists. Skipping ingestion."); - getResponse = aaiClient.getResource(getModelVerUrl(config), distId, AaiRestClient.MimeType.XML); - if ( (getResponse == null) || (getResponse.getStatus() != Response.Status.OK.getStatusCode()) ) { - // Only attempt the PUT if the model-ver doesn't already exist - ClientResponse putResponse = null; + private static final String AAI_MODEL_VER_SUB_URL = "/model-vers/model-ver"; - try { - putResponse = aaiClient.putResource(getModelVerUrl(config), nodeToString(getModelVer()), distId, AaiRestClient.MimeType.XML); - } catch (TransformerException e) { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed for " + getType().toString() + " " + getUniqueIdentifier() - + ": " + e.getMessage() + ". Rolling back distribution."); - return false; + private static final String FAILURE_MSG_PREFIX = "Ingestion failed for "; + private static final String ROLLBACK_MSG_SUFFIX = ". Rolling back distribution."; + + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelArtifact.class.getName()); + + private String modelVerId; + private String modelInvariantId; + private Node modelVer; + private boolean firstVersionOfModel = false; + + public ModelArtifact() { + super(ArtifactType.MODEL); + } + + public String getModelVerId() { + return modelVerId; + } + + public void setModelVerId(String modelVerId) { + this.modelVerId = modelVerId; + } + + public String getModelInvariantId() { + return modelInvariantId; + } + + public void setModelInvariantId(String modelInvariantId) { + this.modelInvariantId = modelInvariantId; + } + + public Node getModelVer() { + return modelVer; + } + + public void setModelVer(Node modelVer) { + this.modelVer = modelVer; + } + + @Override + public String getUniqueIdentifier() { + return getModelInvariantId() + "|" + getModelVerId(); + } + + + /** + * Test whether the specified resource (URL) can be requested successfully + * + * @param aaiClient + * @param distId + * @param xmlResourceUrl + * @return true if a request to GET this resource as XML media is successful (status OK) + */ + private boolean xmlResourceCanBeFetched(AaiRestClient aaiClient, String distId, String xmlResourceUrl) { + OperationResult getResponse = aaiClient.getResource(xmlResourceUrl, distId, MediaType.APPLICATION_XML_TYPE); + return getResponse != null && getResponse.getResultCode() == Response.Status.OK.getStatusCode(); + } + + /** + * PUT the specified XML resource + * + * @param aaiClient + * @param distId + * @param resourceUrl + * @param payload + * @return true if the resource PUT as XML media was successful (status OK) + */ + private boolean putXmlResource(AaiRestClient aaiClient, String distId, String resourceUrl, String payload) { + OperationResult putResponse = + aaiClient.putResource(resourceUrl, payload, distId, MediaType.APPLICATION_XML_TYPE); + return putResponse != null && putResponse.getResultCode() == Response.Status.CREATED.getStatusCode(); + } + + @Override + public boolean push(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, + List<Artifact> completedArtifacts) { + boolean success; + + // See whether the model is already present + String resourceUrl = getModelUrl(config); + + if (xmlResourceCanBeFetched(aaiClient, distId, resourceUrl)) { + logInfoMsg(getType().toString() + " " + getModelInvariantId() + " already exists. Skipping ingestion."); + success = pushModelVersion(aaiClient, config, distId, completedArtifacts); + } else { + // Assume that the model does not exist and attempt the PUT + success = putXmlResource(aaiClient, distId, resourceUrl, getPayload()); + if (success) { + completedArtifacts.add(this); + + // Record state to remember that this is the first version of the model (just added). + firstVersionOfModel = true; + + logInfoMsg(getType().toString() + " " + getUniqueIdentifier() + " successfully ingested."); + } else { + logErrorMsg( + FAILURE_MSG_PREFIX + getType().toString() + " " + getUniqueIdentifier() + ROLLBACK_MSG_SUFFIX); + } } - if ( (putResponse != null) && (putResponse.getStatus() == Response.Status.CREATED.getStatusCode()) ) { - addedModels.add(this); - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getUniqueIdentifier() + " successfully ingested."); + + return success; + } + + /** + * @param aaiClient + * @param config + * @param distId + * @param completedArtifacts + * @return + */ + private boolean pushModelVersion(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, + List<Artifact> completedArtifacts) { + if (xmlResourceCanBeFetched(aaiClient, distId, getModelVerUrl(config))) { + logInfoMsg(getType().toString() + " " + getUniqueIdentifier() + " already exists. Skipping ingestion."); + return true; } - else { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed for " + getType().toString() + " " - + getUniqueIdentifier() + ". Rolling back distribution."); - return false; + + // Load the model version + boolean success = true; + try { + success = putXmlResource(aaiClient, distId, getModelVerUrl(config), nodeToString(getModelVer())); + if (success) { + completedArtifacts.add(this); + logInfoMsg(getType().toString() + " " + getUniqueIdentifier() + " successfully ingested."); + } else { + logErrorMsg( + FAILURE_MSG_PREFIX + getType().toString() + " " + getUniqueIdentifier() + ROLLBACK_MSG_SUFFIX); + } + } catch (TransformerException e) { + logErrorMsg(FAILURE_MSG_PREFIX + getType().toString() + " " + getUniqueIdentifier() + ": " + e.getMessage() + + ROLLBACK_MSG_SUFFIX); + success = false; } - } - else { - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getUniqueIdentifier() + " already exists. Skipping ingestion."); - } - } - - return true; - } - - @Override - public void rollbackModel(AaiRestClient aaiClient, ModelLoaderConfig config, String distId) { - String url = getModelVerUrl(config); - if (firstVersionOfModel) { - // If this was the first version of the model which was added, we want to remove the entire - // model rather than just the version. - url = getModelUrl(config); + + return success; } - - // Best effort to delete. Nothing we can do in the event this fails. - aaiClient.getAndDeleteResource(url, distId); - } - - private String getModelUrl(ModelLoaderConfig config) { - String baseURL = config.getAaiBaseUrl().trim(); - String subURL = null; - String instance = null; - subURL = config.getAaiModelUrl(getModelNamespaceVersion()).trim(); - instance = getModelInvariantId(); - if ( (!baseURL.endsWith("/")) && (!subURL.startsWith("/")) ) { - baseURL = baseURL + "/"; + @Override + public void rollbackModel(AaiRestClient aaiClient, ModelLoaderConfig config, String distId) { + String url = getModelVerUrl(config); + if (firstVersionOfModel) { + // If this was the first version of the model which was added, we want to remove the entire + // model rather than just the version. + url = getModelUrl(config); + } + + // Best effort to delete. Nothing we can do in the event this fails. + aaiClient.getAndDeleteResource(url, distId); } - if ( baseURL.endsWith("/") && subURL.startsWith("/") ) { - baseURL = baseURL.substring(0, baseURL.length()-1); + + private void logInfoMsg(String infoMsg) { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, infoMsg); } - if (!subURL.endsWith("/")) { - subURL = subURL + "/"; + private void logErrorMsg(String errorMsg) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, errorMsg); } - String url = baseURL + subURL + instance; - return url; - } + private String getModelUrl(ModelLoaderConfig config) { + String baseURL = config.getAaiBaseUrl().trim(); + String subURL = config.getAaiModelUrl(getModelNamespaceVersion()).trim(); + String instance = getModelInvariantId(); - private String getModelVerUrl(ModelLoaderConfig config) { - String baseURL = config.getAaiBaseUrl().trim(); - String subURL = null; - String instance = null; + if ((!baseURL.endsWith("/")) && (!subURL.startsWith("/"))) { + baseURL = baseURL + "/"; + } - subURL = config.getAaiModelUrl(getModelNamespaceVersion()).trim() + getModelInvariantId() + AAI_MODEL_VER_SUB_URL; - instance = getModelVerId(); + if (baseURL.endsWith("/") && subURL.startsWith("/")) { + baseURL = baseURL.substring(0, baseURL.length() - 1); + } - if ( (!baseURL.endsWith("/")) && (!subURL.startsWith("/")) ) { - baseURL = baseURL + "/"; - } + if (!subURL.endsWith("/")) { + subURL = subURL + "/"; + } - if ( baseURL.endsWith("/") && subURL.startsWith("/") ) { - baseURL = baseURL.substring(0, baseURL.length()-1); + return baseURL + subURL + instance; } - if (!subURL.endsWith("/")) { - subURL = subURL + "/"; + private String getModelVerUrl(ModelLoaderConfig config) { + String baseURL = config.getAaiBaseUrl().trim(); + String subURL = config.getAaiModelUrl(getModelNamespaceVersion()).trim() + getModelInvariantId() + + AAI_MODEL_VER_SUB_URL; + String instance = getModelVerId(); + + if ((!baseURL.endsWith("/")) && (!subURL.startsWith("/"))) { + baseURL = baseURL + "/"; + } + + if (baseURL.endsWith("/") && subURL.startsWith("/")) { + baseURL = baseURL.substring(0, baseURL.length() - 1); + } + + if (!subURL.endsWith("/")) { + subURL = subURL + "/"; + } + + return baseURL + subURL + instance; } - String url = baseURL + subURL + instance; - return url; - } - - private String nodeToString(Node node) throws TransformerException { - StringWriter sw = new StringWriter(); - Transformer t = TransformerFactory.newInstance().newTransformer(); - t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); - t.transform(new DOMSource(node), new StreamResult(sw)); - return sw.toString(); - } + private String nodeToString(Node node) throws TransformerException { + StringWriter sw = new StringWriter(); + TransformerFactory transFact = TransformerFactory.newInstance(); + transFact.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + Transformer t = transFact.newTransformer(); + t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + t.transform(new DOMSource(node), new StreamResult(sw)); + return sw.toString(); + } } diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactHandler.java b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactHandler.java index 570d8fe..157ac8d 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactHandler.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactHandler.java @@ -20,6 +20,8 @@ */ package org.onap.aai.modelloader.entity.model; +import java.util.List; + import org.onap.aai.modelloader.config.ModelLoaderConfig; import org.onap.aai.modelloader.entity.Artifact; import org.onap.aai.modelloader.entity.ArtifactHandler; @@ -28,56 +30,42 @@ import org.onap.aai.modelloader.service.ModelLoaderMsgs; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; -import java.util.ArrayList; -import java.util.List; - - public class ModelArtifactHandler extends ArtifactHandler { - private static Logger logger = LoggerFactory.getInstance().getLogger(ModelArtifactHandler.class.getName()); - - public ModelArtifactHandler(ModelLoaderConfig config) { - super(config); - } + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelArtifactHandler.class.getName()); - @Override - public boolean pushArtifacts(List<Artifact> artifacts, String distributionID) { - ModelSorter modelSorter = new ModelSorter(); - List<Artifact> sortedModelArtifacts; - try { - sortedModelArtifacts = modelSorter.sort(artifacts); - } - catch (RuntimeException ex) { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Unable to resolve models: " + ex.getMessage()); - return false; + public ModelArtifactHandler(ModelLoaderConfig config) { + super(config); } - - // Push the ordered list of model artifacts to A&AI. If one fails, we need to roll back - // the changes. - List<AbstractModelArtifact> completedModels = new ArrayList<>(); - AaiRestClient aaiClient = new AaiRestClient(config); - for (Artifact art : sortedModelArtifacts) { - AbstractModelArtifact model = (AbstractModelArtifact)art; - if (model.push(aaiClient, config, distributionID, completedModels) != true) { - for (AbstractModelArtifact modelToDelete : completedModels) { - modelToDelete.rollbackModel(aaiClient, config, distributionID); + @Override + public boolean pushArtifacts(List<Artifact> artifacts, String distributionID, List<Artifact> completedArtifacts, + AaiRestClient aaiClient) { + ModelSorter modelSorter = new ModelSorter(); + List<Artifact> sortedModelArtifacts; + try { + sortedModelArtifacts = modelSorter.sort(artifacts); + } catch (RuntimeException ex) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Unable to resolve models: " + ex.getMessage()); + return false; } - return false; - } - } + // Push the ordered list of model artifacts to A&AI. If one fails, we need to roll back the changes. + for (Artifact art : sortedModelArtifacts) { + AbstractModelArtifact model = (AbstractModelArtifact) art; + if (!model.push(aaiClient, config, distributionID, completedArtifacts)) { + return false; + } + } - return true; - } + return true; + } - // This method is used for the test REST interface to load models without an ASDC - public void loadModelTest(byte[] payload) { - List<Artifact> modelArtifacts = new ArrayList<Artifact>(); - ModelArtifactParser parser = new ModelArtifactParser(); - modelArtifacts.addAll(parser.parse(payload, "Test-Artifact")); - ModelSorter modelSorter = new ModelSorter(); - List<Artifact> sortedModelArtifacts = modelSorter.sort(modelArtifacts); - pushArtifacts(sortedModelArtifacts, "Test-Distribution"); - } + @Override + public void rollback(List<Artifact> completedArtifacts, String distributionId, AaiRestClient aaiClient) { + for (Artifact artifactToDelete : completedArtifacts) { + AbstractModelArtifact model = (AbstractModelArtifact) artifactToDelete; + model.rollbackModel(aaiClient, config, distributionId); + } + } } diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactParser.java b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactParser.java index d03c13c..17bdd87 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactParser.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactParser.java @@ -20,172 +20,183 @@ */ package org.onap.aai.modelloader.entity.model; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collector; +import java.util.stream.IntStream; +import javax.xml.XMLConstants; + import org.onap.aai.modelloader.entity.Artifact; import org.onap.aai.modelloader.service.ModelLoaderMsgs; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; -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; - -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - - -public class ModelArtifactParser implements IModelParser { - - private static String MODEL_VER = "model-ver"; - private static String MODEL_VERSION_ID = "model-version-id"; - private static String MODEL_INVARIANT_ID = "model-invariant-id"; - private static String RELATIONSHIP = "relationship"; - private static String RELATIONSHIP_DATA = "relationship-data"; - private static String RELATIONSHIP_KEY = "relationship-key"; - private static String RELATIONSHIP_VALUE = "relationship-value"; - private static String MODEL_ELEMENT_RELATIONSHIP_KEY = "model.model-invariant-id"; - private static String MODEL_VER_ELEMENT_RELATIONSHIP_KEY = "model-ver.model-version-id"; - - private static Logger logger = LoggerFactory.getInstance().getLogger(ModelArtifactParser.class.getName()); - - public List<Artifact> parse(byte[] artifactPayload, String artifactName) { - String payload = new String(artifactPayload); - List<Artifact> modelList = new ArrayList<Artifact>(); - - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - InputSource is = new InputSource(new StringReader(payload)); - Document doc = builder.parse(is); - - ModelArtifact model = parseModel(doc.getDocumentElement(), payload); - - if (model != null) { - logger.info( ModelLoaderMsgs.DISTRIBUTION_EVENT, "Model parsed =====>>>> " - + "Model-invariant-Id: "+ model.getModelInvariantId() - + " Model-Version-Id: "+ model.getModelVerId()); - modelList.add(model); - } - else { - logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse artifact " + artifactName); - return null; - } - } - catch (Exception ex) { - logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse artifact " + artifactName + ": " + ex.getLocalizedMessage()); - } - - return modelList; - } - - private ModelArtifact parseModel(Node modelNode, String payload) { - ModelArtifact model = new ModelArtifact(); - model.setPayload(payload); - - Element e = (Element)modelNode; - model.setModelNamespace(e.getAttribute("xmlns")); - - parseNode(modelNode, model); - - if ( (model.getModelInvariantId() == null) || (model.getModelVerId() == null) ){ - return null; - } - - return model; - } - - private void parseNode(Node node, ModelArtifact model) { - if (node.getNodeName().equalsIgnoreCase(MODEL_INVARIANT_ID)) { - model.setModelInvariantId(node.getTextContent().trim()); - } - else if (node.getNodeName().equalsIgnoreCase(MODEL_VERSION_ID)) { - model.setModelVerId(node.getTextContent().trim()); - } - else if (node.getNodeName().equalsIgnoreCase(RELATIONSHIP)) { - String dependentModelKey = parseRelationshipNode(node, model); - if (dependentModelKey != null) { - model.addDependentModelId(dependentModelKey); - } - } - else { - if (node.getNodeName().equalsIgnoreCase(MODEL_VER)) { - model.setModelVer(node); - if ( (model.getModelNamespace() != null) && (!model.getModelNamespace().isEmpty()) ) { - Element e = (Element) node; - e.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns", model.getModelNamespace()); - } - } - - NodeList nodeList = node.getChildNodes(); - - for (int i = 0; i < nodeList.getLength(); i++) { - Node childNode = nodeList.item(i); - parseNode(childNode, model); - } - } - } - - private String parseRelationshipNode(Node node, ModelArtifact model) { - String currentKey = null; - String currentValue = null; - String modelVersionIdValue = null; - String modelInvariantIdValue = null; - - NodeList nodeList = node.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node childNode = nodeList.item(i); - - if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_DATA)) { - NodeList relDataChildList = childNode.getChildNodes(); - - for (int j = 0; j < relDataChildList.getLength(); j++) { - Node relDataChildNode = relDataChildList.item(j); - - if (relDataChildNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_KEY)) { - currentKey = relDataChildNode.getTextContent().trim(); - - if (currentValue != null) { - if (currentKey.equalsIgnoreCase(MODEL_VER_ELEMENT_RELATIONSHIP_KEY)) { - modelVersionIdValue = currentValue; - } - else if (currentKey.equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY)) { - modelInvariantIdValue = currentValue; - } - - currentKey = null; - currentValue = null; - } - } - else if (relDataChildNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_VALUE)) { - currentValue = relDataChildNode.getTextContent().trim(); - - if (currentKey != null) { - if (currentKey.equalsIgnoreCase(MODEL_VER_ELEMENT_RELATIONSHIP_KEY)) { - modelVersionIdValue = currentValue; - } - else if (currentKey.equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY)) { - modelInvariantIdValue = currentValue; - } - - currentKey = null; - currentValue = null; - } - } - } - } - } - - if ( (modelVersionIdValue != null) && (modelInvariantIdValue != null) ) { - return modelInvariantIdValue + "|" + modelVersionIdValue; - } - - return null; - - } +public class ModelArtifactParser extends AbstractModelArtifactParser { + + public static final String MODEL_VER = "model-ver"; + public static final String MODEL_VERSION_ID = "model-version-id"; + public static final String MODEL_INVARIANT_ID = "model-invariant-id"; + private static final String RELATIONSHIP = "relationship"; + private static final String MODEL_ELEMENT_RELATIONSHIP_KEY = "model." + MODEL_INVARIANT_ID; + private static final String MODEL_VER_ELEMENT_RELATIONSHIP_KEY = MODEL_VER + "." + MODEL_VERSION_ID; + + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelArtifactParser.class.getName()); + + @Override + void parseNode(Node node, IModelArtifact model) { + if (node.getNodeName().equalsIgnoreCase(MODEL_INVARIANT_ID) + || node.getNodeName().equalsIgnoreCase(MODEL_VERSION_ID)) { + setVersionId(model, node); + } else if (node.getNodeName().equalsIgnoreCase(RELATIONSHIP)) { + parseRelationshipNode(node, model); + } else { + if (node.getNodeName().equalsIgnoreCase(MODEL_VER)) { + ((ModelArtifact) model).setModelVer(node); + if ((((ModelArtifact) model).getModelNamespace() != null) + && (!((ModelArtifact) model).getModelNamespace().isEmpty())) { + Element e = (Element) node; + e.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns", + ((ModelArtifact) model).getModelNamespace()); + } + } + + parseChildNodes(node, model); + } + } + + /** + * {@inheritDoc} + */ + @Override + void setVersionId(IModelArtifact model, Node node) { + if (MODEL_INVARIANT_ID.equals(node.getNodeName())) { + ((ModelArtifact) model).setModelInvariantId(node.getTextContent().trim()); + } else if (MODEL_VERSION_ID.equals(node.getNodeName())) { + ((ModelArtifact) model).setModelVerId(node.getTextContent().trim()); + } + } + + /** + * {@inheritDoc} + */ + @Override + ModelId buildModelId(NodeList nodeList) { + return IntStream.range(0, nodeList.getLength()).mapToObj(nodeList::item) + .filter(childNode -> childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_DATA)) + .map(this::getRelationship) // + .collect(Collector.of(ModelId::new, ModelId::setRelationship, (m, p) -> m)); + } + + /** + * Find a relationship key and value pair from the children of the supplied node. + * + * @param node containing children storing relationship keys and values + * @return a pair containing a relationship key and its value. Note: if multiple relationships are found, existing + * values stored in the pair will be overwritten. + */ + private Pair<String, String> getRelationship(Node node) { + Objects.requireNonNull(node); + NodeList relDataChildList = node.getChildNodes(); + Objects.requireNonNull(relDataChildList); + + return IntStream.range(0, relDataChildList.getLength()).mapToObj(relDataChildList::item) + .filter(this::filterRelationshipNode) + .collect(Collector.of(Pair::new, applyRelationshipValue, (p, n) -> p)); + } + + /** + * This method is responsible for creating an instance of {@link ModelArtifactParser.ModelId} + * + * @return IModelId instance of {@link ModelArtifactParser.ModelId} + */ + @Override + IModelId createModelIdInstance() { + return new ModelId(); + } + + private class ModelId implements IModelId { + + private String modelInvariantIdValue; + private String modelVersionIdValue; + + @Override + public void setRelationship(Pair<String, String> p) { + if (p.getKey().equalsIgnoreCase(MODEL_VER_ELEMENT_RELATIONSHIP_KEY)) { + modelVersionIdValue = p.getValue(); + } else if (p.getKey().equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY)) { + modelInvariantIdValue = p.getValue(); + } + } + + @Override + public boolean defined() { + return modelInvariantIdValue != null && modelVersionIdValue != null; + } + + @Override + public String toString() { + return modelInvariantIdValue + "|" + modelVersionIdValue; + } + } + + /** + * {@inheritDoc} + */ + @Override + String buildArtifactParseExceptionMessage(String artifactName, String localisedMessage) { + return "Unable to parse legacy model artifact " + artifactName + ": " + localisedMessage; + } + + /** + * {@inheritDoc} + */ + @Override + IModelArtifact createModelArtifactInstance() { + return new ModelArtifact(); + } + + @Override + boolean modelIsValid(IModelArtifact model) { + return ((ModelArtifact) model).getModelInvariantId() != null && ((ModelArtifact) model).getModelVerId() != null; + } + + /** + * {@inheritDoc} + */ + @Override + boolean processParsedModel(List<Artifact> modelList, String artifactName, IModelArtifact model) { + boolean valid = false; + + if (model != null) { + ModelArtifact modelImpl = (ModelArtifact) model; + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Model parsed =====>>>> " + "Model-invariant-Id: " + + modelImpl.getModelInvariantId() + " Model-Version-Id: " + modelImpl.getModelVerId()); + modelList.add(modelImpl); + valid = true; + } else { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse artifact " + artifactName); + } + + return valid; + } + + /** + * {@inheritDoc} + */ + @Override + String getModelElementRelationshipKey() { + return null; + } + + /** + * {@inheritDoc} + */ + @Override + String getVersionIdNodeName() { + return null; + } } diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/ModelParserFactory.java b/src/main/java/org/onap/aai/modelloader/entity/model/ModelParserFactory.java deleted file mode 100644 index 3f6bf6e..0000000 --- a/src/main/java/org/onap/aai/modelloader/entity/model/ModelParserFactory.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 Amdocs - * =================================================================== - * 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.entity.model; - -import java.io.StringReader; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.onap.aai.modelloader.service.ModelLoaderMsgs; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.InputSource; - -public class ModelParserFactory { - private static Logger logger = LoggerFactory.getInstance().getLogger(ModelParserFactory.class.getName()); - - private static String MODEL_ELEMENT = "model"; - private static String NAMED_QUERY_ELEMENT = "named-query"; - - public static IModelParser createModelParser(byte[] artifactPayload, String artifactName) { - Document doc = null; - - try { - String payload = new String(artifactPayload); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder; - builder = factory.newDocumentBuilder(); - InputSource is = new InputSource(new StringReader(payload)); - doc = builder.parse(is); - } catch (Exception e) { - logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse artifact " + artifactName); - return null; - } - - if (doc.getDocumentElement().getNodeName().equalsIgnoreCase(NAMED_QUERY_ELEMENT)) { - return new NamedQueryArtifactParser(); - } - - if (!doc.getDocumentElement().getNodeName().equalsIgnoreCase(MODEL_ELEMENT)) { - logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse artifact " + artifactName - + ": Invalid root element: " + doc.getDocumentElement().getNodeName()); - return null; - } - - Element e = doc.getDocumentElement(); - String ns = e.getAttribute("xmlns"); - String[] parts = ns.split("/"); - - if (parts.length < 1) { - logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse artifact " + artifactName - + ": Could not parse namespace version"); - return null; - } - - String modelNamespaceVersion = parts[parts.length-1].trim().replace("v", ""); - int version = Integer.parseInt(modelNamespaceVersion); - - if (version > 8) { - return new ModelArtifactParser(); - } - - return new ModelV8ArtifactParser(); - } -} diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/ModelSorter.java b/src/main/java/org/onap/aai/modelloader/entity/model/ModelSorter.java index 41c873e..e8fcf3f 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/ModelSorter.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelSorter.java @@ -20,214 +20,223 @@ */ package org.onap.aai.modelloader.entity.model; -import jline.internal.Log; - import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import jline.internal.Log; import org.onap.aai.modelloader.entity.Artifact; /** - * Utility class to sort the given Models according to their dependencies. - * Example: Given a list of Models [A, B, C] where B depends on A, and A depends - * on C, the sorted result will be [C, A, B] + * Utility class to sort the given Models according to their dependencies.<br> + * Example: Given a list of Models [A, B, C] <br> + * where B depends on A, and A depends on C, the sorted result will be [C, A, B] */ public class ModelSorter { - /** - * Wraps a Model object to form dependencies other Models using Edges. - */ - static class Node { - private final AbstractModelArtifact model; - private final HashSet<Edge> inEdges; - private final HashSet<Edge> outEdges; - - public Node(AbstractModelArtifact model) { - this.model = model; - inEdges = new HashSet<Edge>(); - outEdges = new HashSet<Edge>(); - } + /** + * Wraps a Model object to form dependencies other Models using Edges. + */ + static class Node { - public Node addEdge(Node node) { - Edge edge = new Edge(this, node); - outEdges.add(edge); - node.inEdges.add(edge); - return this; - } + private final AbstractModelArtifact model; + private final HashSet<Edge> inEdges; + private final HashSet<Edge> outEdges; - @Override - public String toString() { - return model.getUniqueIdentifier(); - } + public Node(AbstractModelArtifact model) { + this.model = model; + inEdges = new HashSet<>(); + outEdges = new HashSet<>(); + } - @Override - public boolean equals(Object other) { - AbstractModelArtifact otherModel = ((Node) other).model; - return this.model.getUniqueIdentifier().equals(otherModel.getUniqueIdentifier()); - } + public Node addEdge(Node node) { + Edge edge = new Edge(this, node); + outEdges.add(edge); + node.inEdges.add(edge); + return this; + } - @Override - public int hashCode() { - return this.model.getUniqueIdentifier().hashCode(); - } - } - - /** - * Represents a dependency between two Nodes. - */ - static class Edge { - public final Node from; - public final Node to; - - public Edge(Node from, Node to) { - this.from = from; - this.to = to; - } + @Override + public String toString() { + return model.getUniqueIdentifier(); + } - @Override - public boolean equals(Object obj) { - Edge edge = (Edge) obj; - return edge.from == from && edge.to == to; - } - } - - /** - * Returns the list of models sorted by order of dependency. - * - * @param originalList - * the list that needs to be sorted - * @return a list of sorted models - */ - public List<Artifact> sort(List<Artifact> originalList) { - - if (originalList.size() <= 1) { - return originalList; - } + @Override + public boolean equals(Object other) { + if (other == null || this.getClass() != other.getClass()) { + return false; + } + AbstractModelArtifact otherModel = ((Node) other).model; + return this.model.getUniqueIdentifier().equals(otherModel.getUniqueIdentifier()); + } - Collection<Node> nodes = createNodes(originalList); - Collection<Node> sortedNodes = sortNodes(nodes); - - List<Artifact> sortedModelsList = new ArrayList<Artifact>(sortedNodes.size()); - for (Node node : sortedNodes) { - sortedModelsList.add(node.model); + @Override + public int hashCode() { + return this.model.getUniqueIdentifier().hashCode(); + } } - return sortedModelsList; - } - - /** - * Create nodes from the list of models and their dependencies. - * - * @param models - * what the nodes creation is based upon - * @return Collection of Node objects - */ - private Collection<Node> createNodes(Collection<Artifact> models) { - - // load list of models into a map, so we can later replace referenceIds with - // real Models - HashMap<String, AbstractModelArtifact> versionIdToModelMap = new HashMap<>(); - for (Artifact art : models) { - AbstractModelArtifact ma = (AbstractModelArtifact) art; - versionIdToModelMap.put(ma.getUniqueIdentifier(), ma); - } + /** + * Represents a dependency between two Nodes. + */ + static class Edge { - HashMap<String, Node> nodes = new HashMap<String, Node>(); - // create a node for each model and its referenced models - for (Artifact art : models) { - - AbstractModelArtifact model = (AbstractModelArtifact) art; - - // node might have been created by another model referencing it - Node node = nodes.get(model.getUniqueIdentifier()); - - if (null == node) { - node = new Node(model); - nodes.put(model.getUniqueIdentifier(), node); - } - - for (String referencedModelId : model.getDependentModelIds()) { - // node might have been created by another model referencing it - Node referencedNode = nodes.get(referencedModelId); - - if (null == referencedNode) { - // create node - AbstractModelArtifact referencedModel = versionIdToModelMap.get(referencedModelId); - if (referencedModel == null) { - Log.debug("ignoring " + referencedModelId); - continue; // referenced model not supplied, no need to sort it - } - referencedNode = new Node(referencedModel); - nodes.put(referencedModelId, referencedNode); - } - referencedNode.addEdge(node); - } - } + public final Node from; + public final Node to; - return nodes.values(); - } - - /** - * Sorts the given Nodes by order of dependency. - * - * @param originalList - * the collection of nodes to be sorted - * @return a sorted collection of the given nodes - */ - private Collection<Node> sortNodes(Collection<Node> unsortedNodes) { - // L <- Empty list that will contain the sorted elements - ArrayList<Node> nodeList = new ArrayList<Node>(); - - // S <- Set of all nodes with no incoming edges - HashSet<Node> nodeSet = new HashSet<Node>(); - for (Node unsortedNode : unsortedNodes) { - if (unsortedNode.inEdges.size() == 0) { - nodeSet.add(unsortedNode); - } + public Edge(Node from, Node to) { + this.from = from; + this.to = to; + } + + @Override + public boolean equals(Object obj) { + if (obj == null || this.getClass() != obj.getClass()) { + return false; + } + Edge edge = (Edge) obj; + return edge.from == from && edge.to == to; + } + + @Override + public int hashCode() { + return Objects.hash(this.from, this.to); + } } - // while S is non-empty do - while (!nodeSet.isEmpty()) { - // remove a node n from S - Node node = nodeSet.iterator().next(); - nodeSet.remove(node); + /** + * Returns the list of models sorted by order of dependency. + * + * @param originalList the list that needs to be sorted + * @return a list of sorted models + */ + public List<Artifact> sort(List<Artifact> originalList) { - // insert n into L - nodeList.add(node); + if (originalList.size() <= 1) { + return originalList; + } - // for each node m with an edge e from n to m do - for (Iterator<Edge> it = node.outEdges.iterator(); it.hasNext();) { - // remove edge e from the graph - Edge edge = it.next(); - Node to = edge.to; - it.remove();// Remove edge from n - to.inEdges.remove(edge);// Remove edge from m + Collection<Node> nodes = createNodes(originalList); + Collection<Node> sortedNodes = sortNodes(nodes); - // if m has no other incoming edges then insert m into S - if (to.inEdges.isEmpty()) { - nodeSet.add(to); + List<Artifact> sortedModelsList = new ArrayList<>(sortedNodes.size()); + for (Node node : sortedNodes) { + sortedModelsList.add(node.model); } - } - } - // Check to see if all edges are removed - boolean cycle = false; - for (Node node : unsortedNodes) { - if (!node.inEdges.isEmpty()) { - cycle = true; - break; - } + + return sortedModelsList; } - if (cycle) { - throw new RuntimeException( - "Circular dependency present between models, topological sort not possible"); + + /** + * Create nodes from the list of models and their dependencies. + * + * @param models what the nodes creation is based upon + * @return Collection of Node objects + */ + private Collection<Node> createNodes(Collection<Artifact> models) { + + // load list of models into a map, so we can later replace referenceIds with real Models + Map<String, AbstractModelArtifact> versionIdToModelMap = new HashMap<>(); + for (Artifact art : models) { + AbstractModelArtifact ma = (AbstractModelArtifact) art; + versionIdToModelMap.put(ma.getUniqueIdentifier(), ma); + } + + Map<String, Node> nodes = new HashMap<>(); + // create a node for each model and its referenced models + for (Artifact art : models) { + + AbstractModelArtifact model = (AbstractModelArtifact) art; + + // node might have been created by another model referencing it + Node node = nodes.get(model.getUniqueIdentifier()); + + if (null == node) { + node = new Node(model); + nodes.put(model.getUniqueIdentifier(), node); + } + + for (String referencedModelId : model.getDependentModelIds()) { + // node might have been created by another model referencing it + Node referencedNode = nodes.get(referencedModelId); + + if (null == referencedNode) { + // create node + AbstractModelArtifact referencedModel = versionIdToModelMap.get(referencedModelId); + if (referencedModel == null) { + Log.debug("ignoring " + referencedModelId); + continue; // referenced model not supplied, no need to sort it + } + referencedNode = new Node(referencedModel); + nodes.put(referencedModelId, referencedNode); + } + referencedNode.addEdge(node); + } + } + + return nodes.values(); } - return nodeList; - } + /** + * Sorts the given Nodes by order of dependency. + * + * @param unsortedNodes the collection of nodes to be sorted + * @return a sorted collection of the given nodes + */ + private Collection<Node> sortNodes(Collection<Node> unsortedNodes) { + // L <- Empty list that will contain the sorted elements + List<Node> nodeList = new ArrayList<>(); + + // S <- Set of all nodes with no incoming edges + Set<Node> nodeSet = new HashSet<>(); + for (Node unsortedNode : unsortedNodes) { + if (unsortedNode.inEdges.isEmpty()) { + nodeSet.add(unsortedNode); + } + } + // while S is non-empty do + while (!nodeSet.isEmpty()) { + // remove a node n from S + Node node = nodeSet.iterator().next(); + nodeSet.remove(node); + + // insert n into L + nodeList.add(node); + + // for each node m with an edge e from n to m do + for (Iterator<Edge> it = node.outEdges.iterator(); it.hasNext();) { + // remove edge e from the graph + Edge edge = it.next(); + Node to = edge.to; + it.remove();// Remove edge from n + to.inEdges.remove(edge);// Remove edge from m + + // if m has no other incoming edges then insert m into S + if (to.inEdges.isEmpty()) { + nodeSet.add(to); + } + } + } + // Check to see if all edges are removed + boolean cycle = false; + for (Node node : unsortedNodes) { + if (!node.inEdges.isEmpty()) { + cycle = true; + break; + } + } + if (cycle) { + throw new RuntimeException("Circular dependency present between models, topological sort not possible"); + } + + return nodeList; + } } diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/ModelV8Artifact.java b/src/main/java/org/onap/aai/modelloader/entity/model/ModelV8Artifact.java deleted file mode 100644 index cd7afef..0000000 --- a/src/main/java/org/onap/aai/modelloader/entity/model/ModelV8Artifact.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 Amdocs - * =================================================================== - * 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.entity.model; - -import java.util.List; - -import javax.ws.rs.core.Response; - -import org.onap.aai.modelloader.config.ModelLoaderConfig; -import org.onap.aai.modelloader.entity.Artifact; -import org.onap.aai.modelloader.entity.ArtifactType; -import org.onap.aai.modelloader.restclient.AaiRestClient; -import org.onap.aai.modelloader.service.ModelLoaderMsgs; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; - -import com.sun.jersey.api.client.ClientResponse; - -public class ModelV8Artifact extends AbstractModelArtifact { - private static String AAI_CONVERSION_URL = "/aai/tools/modeltransform"; - - private static Logger logger = LoggerFactory.getInstance().getLogger(ModelArtifact.class.getName()); - - private String modelNameVersionId; - private ModelArtifact translatedModel; - - public ModelV8Artifact() { - super(ArtifactType.MODEL_V8); - } - - public String getModelNameVersionId() { - return modelNameVersionId; - } - - public void setModelNameVersionId(String modelNameVersionId) { - this.modelNameVersionId = modelNameVersionId; - } - - @Override - public String getUniqueIdentifier() { - return getModelNameVersionId(); - } - - @Override - public boolean push(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, List<AbstractModelArtifact> addedModels) { - // For a legacy model (version <= v8), we need to call out to an A&AI endpoint to convert to the proper format - ClientResponse response = aaiClient.postResource(getConversionUrl(config), constructTransformPayload(), distId, AaiRestClient.MimeType.XML); - if ( (response == null) || (response.getStatus() != Response.Status.OK.getStatusCode()) ) { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed for " + - getType().toString() + " " + getModelNameVersionId() + ". Unable to convert model. Rolling back distribution."); - return false; - } - - String translatedPayload = response.getEntity(String.class); - - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Translated artifact payload:\n" + translatedPayload); - - ModelArtifactParser parser = new ModelArtifactParser(); - - List<Artifact> parsedArtifacts = parser.parse(translatedPayload.getBytes(), "translated-payload"); - if (parsedArtifacts == null || parsedArtifacts.isEmpty()) { - return false; - } - - translatedModel = (ModelArtifact)parsedArtifacts.get(0); - return translatedModel.push(aaiClient, config, distId, addedModels); - } - - @Override - public void rollbackModel(AaiRestClient aaiClient, ModelLoaderConfig config, String distId) { - if (translatedModel != null) { - translatedModel.rollbackModel(aaiClient, config, distId); - } - } - - - private String constructTransformPayload() { - // A&AI requires that to transform a legacy model, we need to use the v8 namespace (even - // if the version < 8) - return getPayload().replaceFirst("aai.inventory/v.", "aai.inventory/v8"); - } - - private String getConversionUrl(ModelLoaderConfig config) { - String baseUrl = config.getAaiBaseUrl().trim(); - String subUrl = AAI_CONVERSION_URL; - - if ( (!baseUrl.endsWith("/")) && (!subUrl.startsWith("/")) ) { - baseUrl = baseUrl + "/"; - } - - if ( baseUrl.endsWith("/") && subUrl.startsWith("/") ) { - baseUrl = baseUrl.substring(0, baseUrl.length()-1); - } - - if (!subUrl.endsWith("/")) { - subUrl = subUrl + "/"; - } - - String url = baseUrl + subUrl; - return url; - } -} diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/ModelV8ArtifactParser.java b/src/main/java/org/onap/aai/modelloader/entity/model/ModelV8ArtifactParser.java deleted file mode 100644 index 0e0c88b..0000000 --- a/src/main/java/org/onap/aai/modelloader/entity/model/ModelV8ArtifactParser.java +++ /dev/null @@ -1,133 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 Amdocs - * =================================================================== - * 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.entity.model; - -import org.onap.aai.modelloader.entity.Artifact; -import org.onap.aai.modelloader.service.ModelLoaderMsgs; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -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; - -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - - -public class ModelV8ArtifactParser implements IModelParser { - - private static String MODEL_NAME_VERSION_ID = "model-name-version-id"; - private static String RELATIONSHIP_DATA = "relationship-data"; - private static String RELATIONSHIP_KEY = "relationship-key"; - private static String RELATIONSHIP_VALUE = "relationship-value"; - private static String MODEL_ELEMENT_RELATIONSHIP_KEY = "model.model-name-version-id"; - - - private static Logger logger = LoggerFactory.getInstance().getLogger(ModelV8ArtifactParser.class.getName()); - @Override - public List<Artifact> parse(byte[] artifactPayload, String artifactName) { - String payload = new String(artifactPayload); - List<Artifact> modelList = new ArrayList<>(); - - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - InputSource is = new InputSource(new StringReader(payload)); - Document doc = builder.parse(is); - - ModelV8Artifact model = parseModel(doc.getDocumentElement(), payload); - - if (model != null) { - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Model parsed =====>>>> " + "Model-Named-Version-Id: "+ model.getModelNameVersionId()); - modelList.add(model); - } - else { - logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse legacy model artifact " + artifactName); - return null; - } - } - catch (Exception ex) { - logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse legacy model artifact " + artifactName + ": " + ex.getLocalizedMessage()); - } - - return modelList; - } - - private ModelV8Artifact parseModel(Node modelNode, String payload) { - ModelV8Artifact model = new ModelV8Artifact(); - model.setPayload(payload); - - Element e = (Element)modelNode; - model.setModelNamespace(e.getAttribute("xmlns")); - - parseNode(modelNode, model); - - if (model.getModelNameVersionId() == null) { - return null; - } - - return model; - } - - private void parseNode(Node node, ModelV8Artifact model) { - if (node.getNodeName().equalsIgnoreCase(MODEL_NAME_VERSION_ID)) { - model.setModelNameVersionId(node.getTextContent().trim()); - } - else if (node.getNodeName().equalsIgnoreCase(RELATIONSHIP_DATA)) { - parseRelationshipNode(node, model); - } - else { - NodeList nodeList = node.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node childNode = nodeList.item(i); - parseNode(childNode, model); - } - } - } - - private void parseRelationshipNode(Node node, ModelV8Artifact model) { - String key = null; - String value = null; - - NodeList nodeList = node.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node childNode = nodeList.item(i); - if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_KEY)) { - key = childNode.getTextContent().trim(); - } - else if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_VALUE)) { - value = childNode.getTextContent().trim(); - } - } - - if ( (key != null) && (key.equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY )) && (value != null) ) { - - model.addDependentModelId(value); - - } - } -} diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifact.java b/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifact.java index 1e1f3a2..668a751 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifact.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifact.java @@ -21,7 +21,7 @@ package org.onap.aai.modelloader.entity.model; import java.util.List; - +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.onap.aai.modelloader.config.ModelLoaderConfig; @@ -31,81 +31,80 @@ import org.onap.aai.modelloader.service.ModelLoaderMsgs; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; -import com.sun.jersey.api.client.ClientResponse; +import org.onap.aai.modelloader.entity.Artifact; +import org.onap.aai.restclient.client.OperationResult; public class NamedQueryArtifact extends AbstractModelArtifact { - - private Logger logger = LoggerFactory.getInstance().getLogger(NamedQueryArtifact.class.getName()); - - private String namedQueryUuid; - - public NamedQueryArtifact() { - super(ArtifactType.NAMED_QUERY); - } - - public String getNamedQueryUuid() { - return namedQueryUuid; - } - - public void setNamedQueryUuid(String namedQueryUuid) { - this.namedQueryUuid = namedQueryUuid; - } - - @Override - public String getUniqueIdentifier() { - return getNamedQueryUuid(); - } - - @Override - public boolean push(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, List<AbstractModelArtifact> addedModels) { - ClientResponse getResponse = aaiClient.getResource(getNamedQueryUrl(config), distId, AaiRestClient.MimeType.XML); - if ( (getResponse == null) || (getResponse.getStatus() != Response.Status.OK.getStatusCode()) ) { - // Only attempt the PUT if the model doesn't already exist - ClientResponse putResponse = aaiClient.putResource(getNamedQueryUrl(config), getPayload(), distId, AaiRestClient.MimeType.XML); - if ( (putResponse != null) && (putResponse.getStatus() == Response.Status.CREATED.getStatusCode()) ) { - addedModels.add(this); - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getUniqueIdentifier() + " successfully ingested."); - } - else { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed for " + getType().toString() + " " + getUniqueIdentifier() + - ". Rolling back distribution."); - return false; - } + + private Logger logger = LoggerFactory.getInstance().getLogger(NamedQueryArtifact.class.getName()); + + private String namedQueryUuid; + + public NamedQueryArtifact() { + super(ArtifactType.NAMED_QUERY); } - else { - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getUniqueIdentifier() + " already exists. Skipping ingestion."); + + public String getNamedQueryUuid() { + return namedQueryUuid; + } + + public void setNamedQueryUuid(String namedQueryUuid) { + this.namedQueryUuid = namedQueryUuid; } - - return true; - } - - @Override - public void rollbackModel(AaiRestClient aaiClient, ModelLoaderConfig config, String distId) { - // Best effort to delete. Nothing we can do in the event this fails. - aaiClient.getAndDeleteResource(getNamedQueryUrl(config), distId); - } - - private String getNamedQueryUrl(ModelLoaderConfig config) { - String baseURL = config.getAaiBaseUrl().trim(); - String subURL = null; - String instance = null; - - subURL = config.getAaiNamedQueryUrl(getModelNamespaceVersion()).trim(); - instance = this.getNamedQueryUuid(); - - if ( (!baseURL.endsWith("/")) && (!subURL.startsWith("/")) ) { - baseURL = baseURL + "/"; + + @Override + public String getUniqueIdentifier() { + return getNamedQueryUuid(); } - if ( baseURL.endsWith("/") && subURL.startsWith("/") ) { - baseURL = baseURL.substring(0, baseURL.length()-1); + @Override + public boolean push(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, List<Artifact> completedArtifacts) { + OperationResult getResponse = + aaiClient.getResource(getNamedQueryUrl(config), distId, MediaType.APPLICATION_XML_TYPE); + if ((getResponse == null) || (getResponse.getResultCode() != Response.Status.OK.getStatusCode())) { + // Only attempt the PUT if the model doesn't already exist + OperationResult putResponse = aaiClient.putResource(getNamedQueryUrl(config), getPayload(), distId, + MediaType.APPLICATION_XML_TYPE); + if ((putResponse != null) && (putResponse.getResultCode() == Response.Status.CREATED.getStatusCode())) { + completedArtifacts.add(this); + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + getType().toString() + " " + getUniqueIdentifier() + " successfully ingested."); + } else { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed for " + getType().toString() + + " " + getUniqueIdentifier() + ". Rolling back distribution."); + return false; + } + } else { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + getType().toString() + " " + getUniqueIdentifier() + " already exists. Skipping ingestion."); + } + + return true; } - if (!subURL.endsWith("/")) { - subURL = subURL + "/"; + @Override + public void rollbackModel(AaiRestClient aaiClient, ModelLoaderConfig config, String distId) { + // Best effort to delete. Nothing we can do in the event this fails. + aaiClient.getAndDeleteResource(getNamedQueryUrl(config), distId); } - String url = baseURL + subURL + instance; - return url; - } + private String getNamedQueryUrl(ModelLoaderConfig config) { + String baseURL = config.getAaiBaseUrl().trim(); + String subURL = config.getAaiNamedQueryUrl(getModelNamespaceVersion()).trim(); + String instance = this.getNamedQueryUuid(); + + if ((!baseURL.endsWith("/")) && (!subURL.startsWith("/"))) { + baseURL = baseURL + "/"; + } + + if (baseURL.endsWith("/") && subURL.startsWith("/")) { + baseURL = baseURL.substring(0, baseURL.length() - 1); + } + + if (!subURL.endsWith("/")) { + subURL = subURL + "/"; + } + + return baseURL + subURL + instance; + } } diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifactParser.java b/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifactParser.java index 8188b28..5b9488e 100644 --- a/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifactParser.java +++ b/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifactParser.java @@ -20,114 +20,86 @@ */ package org.onap.aai.modelloader.entity.model; +import java.util.List; + import org.onap.aai.modelloader.entity.Artifact; import org.onap.aai.modelloader.service.ModelLoaderMsgs; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; -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; - -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; +import org.w3c.dom.Node; -public class NamedQueryArtifactParser implements IModelParser { +public class NamedQueryArtifactParser extends AbstractModelArtifactParser { - private static String NAMED_QUERY_VERSION_ID = "named-query-uuid"; - private static String RELATIONSHIP_DATA = "relationship-data"; - private static String RELATIONSHIP_KEY = "relationship-key"; - private static String RELATIONSHIP_VALUE = "relationship-value"; - private static String MODEL_ELEMENT_RELATIONSHIP_KEY = "model.model-invariant-id"; + private static final String NAMED_QUERY_VERSION_ID = "named-query-uuid"; + private static final String MODEL_ELEMENT_RELATIONSHIP_KEY = "model.model-invariant-id"; - - private static Logger logger = LoggerFactory.getInstance().getLogger(NamedQueryArtifactParser.class.getName()); - - public List<Artifact> parse(byte[] artifactPayload, String artifactName) { - String payload = new String(artifactPayload); - List<Artifact> modelList = new ArrayList<Artifact>(); + private static Logger logger = LoggerFactory.getInstance().getLogger(NamedQueryArtifactParser.class.getName()); - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - InputSource is = new InputSource(new StringReader(payload)); - Document doc = builder.parse(is); + /** + * {@inheritDoc} + */ + @Override + boolean processParsedModel(List<Artifact> modelList, String artifactName, IModelArtifact model) { + boolean valid = false; - NamedQueryArtifact model = parseModel(doc.getDocumentElement(), payload); + if (model != null) { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + "Named-Query parsed =====>>>> " + "Named-Query-UUID: " + ((NamedQueryArtifact) model) + .getNamedQueryUuid()); + modelList.add((NamedQueryArtifact) model); - if (model != null) { - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Named-Query parsed =====>>>> " + "Named-Query-UUID: "+ model.getNamedQueryUuid()); - modelList.add(model); - } - else { - logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse named-query artifact " + artifactName); - return null; - } - } - catch (Exception ex) { - logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse named-query artifact " + artifactName + ": " + ex.getLocalizedMessage()); - } + valid = true; + } else { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, + "Unable to parse named-query artifact " + artifactName); + } - return modelList; - } + return valid; + } - private NamedQueryArtifact parseModel(Node modelNode, String payload) { - NamedQueryArtifact model = new NamedQueryArtifact(); - model.setPayload(payload); + /** + * {@inheritDoc} + */ + @Override + String buildArtifactParseExceptionMessage(String artifactName, String localisedMessage) { + return "Unable to parse named-query artifact " + artifactName + ": " + localisedMessage; + } - Element e = (Element)modelNode; - model.setModelNamespace(e.getAttribute("xmlns")); + @Override + String getModelElementRelationshipKey() { + return MODEL_ELEMENT_RELATIONSHIP_KEY; + } - parseNode(modelNode, model); + /** + * {@inheritDoc} + */ + @Override + String getVersionIdNodeName() { + return NAMED_QUERY_VERSION_ID; + } - if (model.getNamedQueryUuid() == null) { - return null; + /** + * {@inheritDoc} + */ + @Override + void setVersionId(IModelArtifact model, Node node) { + ((NamedQueryArtifact) model).setNamedQueryUuid(node.getTextContent().trim()); } - return model; - } - - private void parseNode(Node node, NamedQueryArtifact model) { - if (node.getNodeName().equalsIgnoreCase(NAMED_QUERY_VERSION_ID)) { - model.setNamedQueryUuid(node.getTextContent().trim()); - } - else if (node.getNodeName().equalsIgnoreCase(RELATIONSHIP_DATA)) { - parseRelationshipNode(node, model); - } - else { - NodeList nodeList = node.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node childNode = nodeList.item(i); - parseNode(childNode, model); - } - } - } - - private void parseRelationshipNode(Node node, NamedQueryArtifact model) { - String key = null; - String value = null; - - NodeList nodeList = node.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node childNode = nodeList.item(i); - if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_KEY)) { - key = childNode.getTextContent().trim(); - } - else if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_VALUE)) { - value = childNode.getTextContent().trim(); - } + /** + * {@inheritDoc} + */ + @Override + IModelArtifact createModelArtifactInstance() { + return new NamedQueryArtifact(); } - - if ( (key != null) && (key.equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY )) ) { - if (value != null) { - model.addDependentModelId(value); - } + + /** + * {@inheritDoc} + */ + @Override + boolean modelIsValid(IModelArtifact model) { + return ((NamedQueryArtifact) model).getNamedQueryUuid() != null; } - } } diff --git a/src/main/java/org/onap/aai/modelloader/entity/model/Pair.java b/src/main/java/org/onap/aai/modelloader/entity/model/Pair.java new file mode 100644 index 0000000..ede60eb --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/entity/model/Pair.java @@ -0,0 +1,54 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.entity.model; + +/** + * Utility class to pair a key and value + * + * @param <K> key + * @param <V> value + */ +class Pair<K, V> { + private K key; + private V value; + + public void setKey(K key) { + this.key = key; + } + + public K getKey() { + return key; + } + + public void setValue(V value) { + this.value = value; + } + + public V getValue() { + return value; + } + + @Override + public String toString() { + return key + "=" + value; + } +} diff --git a/src/main/java/org/onap/aai/modelloader/extraction/ArtifactInfoExtractor.java b/src/main/java/org/onap/aai/modelloader/extraction/ArtifactInfoExtractor.java new file mode 100644 index 0000000..7dbc34f --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/extraction/ArtifactInfoExtractor.java @@ -0,0 +1,62 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.util.ArrayList; +import java.util.List; +import org.openecomp.sdc.api.notification.IArtifactInfo; +import org.openecomp.sdc.api.notification.INotificationData; +import org.openecomp.sdc.api.notification.IResourceInstance; + +/** + * This class is responsible for extracting implementations of IArtifactInto from an implementation of + * INotificationData. + */ +public class ArtifactInfoExtractor { + + /** + * This method is responsible for extracting a collection of IArtifactInfo objects from a given instance of + * INotificationData. + * <p/> + * + * @param data an object that may contain instances of IArtifactInfo + * @return List<IArtifactInfo> instances of IArtifactInfo extracted from the given data + */ + public List<IArtifactInfo> extract(INotificationData data) { + List<IArtifactInfo> artifacts = new ArrayList<>(); + + if (data != null) { + if (data.getServiceArtifacts() != null) { + artifacts.addAll(data.getServiceArtifacts()); + } + + if (data.getResources() != null) { + for (IResourceInstance resource : data.getResources()) { + if (resource.getArtifacts() != null) { + artifacts.addAll(resource.getArtifacts()); + } + } + } + } + + return artifacts; + } +} diff --git a/src/main/java/org/onap/aai/modelloader/extraction/InvalidArchiveException.java b/src/main/java/org/onap/aai/modelloader/extraction/InvalidArchiveException.java new file mode 100644 index 0000000..5e6353f --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/extraction/InvalidArchiveException.java @@ -0,0 +1,48 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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; + +/** + * This class represents an exception encountered when processing an archive in memory. + */ +public class InvalidArchiveException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + public InvalidArchiveException(String message) { + super(message); + } + + /** + * Constructor for an instance of this exception with a message and actual exception encountered. + * + * @param message information about the exception + * @param cause the actual exception that was encountered + */ + InvalidArchiveException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/aai/modelloader/notification/ArtifactDeploymentManager.java b/src/main/java/org/onap/aai/modelloader/notification/ArtifactDeploymentManager.java new file mode 100644 index 0000000..6d75306 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/notification/ArtifactDeploymentManager.java @@ -0,0 +1,123 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.notification; + +import java.util.ArrayList; +import java.util.List; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.entity.Artifact; +import org.onap.aai.modelloader.entity.catalog.VnfCatalogArtifactHandler; +import org.onap.aai.modelloader.entity.model.ModelArtifactHandler; +import org.onap.aai.modelloader.restclient.AaiRestClient; +import org.openecomp.sdc.api.IDistributionClient; +import org.openecomp.sdc.api.notification.IArtifactInfo; +import org.openecomp.sdc.api.notification.INotificationData; + +/** + * This class is responsible for deploying model and catalog artifacts. + */ +public class ArtifactDeploymentManager { + + private IDistributionClient client; + private ModelLoaderConfig config; + private ModelArtifactHandler modelArtifactHandler; + private VnfCatalogArtifactHandler vnfCatalogArtifactHandler; + private NotificationPublisher notificationPublisher; + + public ArtifactDeploymentManager(IDistributionClient client, ModelLoaderConfig config) { + this.client = client; + this.config = config; + } + + /** + * Deploys model and catalog artifacts to A&AI + * + * @param data data about the notification that is being processed + * @param artifacts the specific artifacts found in the data. + * @param modelArtifacts collection of artifacts that represent yml files found in a TOSCA_CSAR file that have been + * converted to XML and also those for model query specs + * @param catalogArtifacts collection of artifacts that represent vnf catalog files + * @return boolean <code>true</code> if all deployments were successful otherwise <code>false</code> + */ + public boolean deploy(final INotificationData data, final List<IArtifactInfo> artifacts, + final List<Artifact> modelArtifacts, final List<Artifact> catalogArtifacts) { + + AaiRestClient aaiClient = new AaiRestClient(config); + String distributionId = data.getDistributionID(); + + List<Artifact> completedArtifacts = new ArrayList<>(); + boolean deploySuccess = + getModelArtifactHandler().pushArtifacts(modelArtifacts, distributionId, completedArtifacts, aaiClient); + + if (!deploySuccess) { + getModelArtifactHandler().rollback(completedArtifacts, distributionId, aaiClient); + } else { + List<Artifact> completedImageData = new ArrayList<>(); + deploySuccess = getVnfCatalogArtifactHandler().pushArtifacts(catalogArtifacts, distributionId, + completedImageData, aaiClient); + if (!deploySuccess) { + getModelArtifactHandler().rollback(completedArtifacts, distributionId, aaiClient); + getVnfCatalogArtifactHandler().rollback(completedImageData, distributionId, aaiClient); + } + } + + publishNotifications(data, "TOSCA_CSAR", artifacts, deploySuccess); + + return deploySuccess; + } + + private void publishNotifications(INotificationData data, String filterType, List<IArtifactInfo> artifacts, + boolean deploymentSuccess) { + if (deploymentSuccess) { + artifacts.stream().filter(a -> filterType.equalsIgnoreCase(a.getArtifactType())) + .forEach(a -> getNotificationPublisher().publishDeploySuccess(client, data, a)); + getNotificationPublisher().publishComponentSuccess(client, data); + } else { + artifacts.stream().filter(a -> filterType.equalsIgnoreCase(a.getArtifactType())) + .forEach(a -> getNotificationPublisher().publishDeployFailure(client, data, a)); + getNotificationPublisher().publishComponentFailure(client, data, "deploy failure"); + } + } + + private ModelArtifactHandler getModelArtifactHandler() { + if (modelArtifactHandler == null) { + modelArtifactHandler = new ModelArtifactHandler(config); + } + + return modelArtifactHandler; + } + + private NotificationPublisher getNotificationPublisher() { + if (notificationPublisher == null) { + notificationPublisher = new NotificationPublisher(); + } + + return notificationPublisher; + } + + private VnfCatalogArtifactHandler getVnfCatalogArtifactHandler() { + if (vnfCatalogArtifactHandler == null) { + this.vnfCatalogArtifactHandler = new VnfCatalogArtifactHandler(config); + } + + return vnfCatalogArtifactHandler; + } +} diff --git a/src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java b/src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java new file mode 100644 index 0000000..bdd101e --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/notification/ArtifactDownloadManager.java @@ -0,0 +1,250 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.notification; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.babel.service.data.BabelArtifact.ArtifactType; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.cl.mdc.MdcContext; +import org.onap.aai.cl.mdc.MdcOverride; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.entity.Artifact; +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.restclient.BabelServiceClient; +import org.onap.aai.modelloader.service.ModelLoaderMsgs; +import org.openecomp.sdc.api.IDistributionClient; +import org.openecomp.sdc.api.notification.IArtifactInfo; +import org.openecomp.sdc.api.notification.INotificationData; +import org.openecomp.sdc.api.results.IDistributionClientDownloadResult; +import org.openecomp.sdc.utils.ArtifactTypeEnum; +import org.openecomp.sdc.utils.DistributionActionResultEnum; + +/** + * This class is responsible for downloading the artifacts from the ASDC. + * + * The downloads can be TOSCA_CSAR files or VNF_CATALOG files. + * + * The status of the download is published. The status of the extraction of yml files from a TOSCA_CSAR file is also + * published as a deployment event. + * + * TOSCA_CSAR file artifacts will be converted into XML and returned as model artifacts. + */ +public class ArtifactDownloadManager { + + private static Logger logger = LoggerFactory.getInstance().getLogger(ArtifactDownloadManager.class); + + private IDistributionClient client; + private NotificationPublisher notificationPublisher; + private BabelArtifactConverter babelArtifactConverter; + private ModelLoaderConfig config; + + public ArtifactDownloadManager(IDistributionClient client, ModelLoaderConfig config) { + this.client = client; + this.config = config; + } + + /** + * This method downloads the artifacts from the ASDC. + * + * @param data data about the notification that is being processed + * @param artifacts the specific artifacts found in the data. + * @param modelArtifacts collection of artifacts for model query specs + * @param catalogArtifacts collection of artifacts that represent vnf catalog files + * @return boolean <code>true</code> if the download process was successful otherwise <code>false</code> + */ + boolean downloadArtifacts(INotificationData data, List<IArtifactInfo> artifacts, List<Artifact> modelArtifacts, + List<Artifact> catalogArtifacts) { + boolean success = true; + + for (IArtifactInfo artifact : artifacts) { + try { + IDistributionClientDownloadResult downloadResult = downloadIndividualArtifacts(data, artifact); + processDownloadedArtifacts(modelArtifacts, catalogArtifacts, artifact, downloadResult, data); + } catch (DownloadFailureException e) { + getNotificationPublisher().publishDownloadFailure(client, data, artifact, e.getMessage()); + success = false; + } catch (Exception e) { + getNotificationPublisher().publishDeployFailure(client, data, artifact); + success = false; + } + + if (!success) { + break; + } + } + + return success; + } + + private IDistributionClientDownloadResult downloadIndividualArtifacts(INotificationData data, + IArtifactInfo artifact) throws DownloadFailureException { + // Grab the current time so we can measure the download time for the metrics log + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + MdcOverride override = new MdcOverride(); + override.addAttribute(MdcContext.MDC_START_TIME, ZonedDateTime.now().format(formatter)); + + IDistributionClientDownloadResult downloadResult = client.download(artifact); + + logger.info(ModelLoaderMsgs.DOWNLOAD_COMPLETE, downloadResult.getDistributionActionResult().toString(), + downloadResult.getArtifactPayload() == null ? "null" + : Base64.getEncoder().encodeToString(downloadResult.getArtifactPayload())); + + if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Downloaded artifact: " + artifact.getArtifactName()); + getNotificationPublisher().publishDownloadSuccess(client, data, artifact); + } else { + throw new DownloadFailureException(downloadResult.getDistributionMessageResult()); + } + + return downloadResult; + } + + private void processDownloadedArtifacts(List<Artifact> modelArtifacts, List<Artifact> catalogArtifacts, + IArtifactInfo artifactInfo, IDistributionClientDownloadResult downloadResult, INotificationData data) + throws ProcessToscaArtifactsException, InvalidArchiveException, BabelArtifactParsingException { + if ("TOSCA_CSAR".equalsIgnoreCase(artifactInfo.getArtifactType())) { + processToscaArtifacts(modelArtifacts, catalogArtifacts, downloadResult.getArtifactPayload(), artifactInfo, + data.getDistributionID(), data.getServiceVersion()); + } else if (ArtifactTypeEnum.MODEL_QUERY_SPEC.toString().equalsIgnoreCase(artifactInfo.getArtifactType())) { + processModelQuerySpecArtifact(modelArtifacts, downloadResult); + } else { + logger.info(ModelLoaderMsgs.UNSUPPORTED_ARTIFACT_TYPE, artifactInfo.getArtifactName(), + artifactInfo.getArtifactType()); + throw new InvalidArchiveException("Unsupported artifact type: " + artifactInfo.getArtifactType()); + } + } + + public void processToscaArtifacts(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); + + List<BabelArtifact> babelArtifacts = + babelClient.postArtifact(payload, artifactInfo.getArtifactName(), serviceVersion, distributionId); + + // Sort Babel artifacts based on type + Map<ArtifactType, List<BabelArtifact>> artifactMap = + babelArtifacts.stream().collect(Collectors.groupingBy(BabelArtifact::getType)); + + if (artifactMap.containsKey(BabelArtifact.ArtifactType.MODEL)) { + modelArtifacts.addAll( + getBabelArtifactConverter().convertToModel(artifactMap.get(BabelArtifact.ArtifactType.MODEL))); + artifactMap.remove(BabelArtifact.ArtifactType.MODEL); + } + + if (artifactMap.containsKey(BabelArtifact.ArtifactType.VNFCATALOG)) { + catalogArtifacts.addAll(getBabelArtifactConverter() + .convertToCatalog(artifactMap.get(BabelArtifact.ArtifactType.VNFCATALOG))); + artifactMap.remove(BabelArtifact.ArtifactType.VNFCATALOG); + } + + // Log unexpected artifact types + if (!artifactMap.isEmpty()) { + logger.warn(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, + artifactInfo.getArtifactName() + " " + serviceVersion + + ". Unexpected artifact types returned by the babel service: " + + artifactMap.keySet().toString()); + } + + } catch (BabelArtifactParsingException e) { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, + "Error for artifact " + artifactInfo.getArtifactName() + " " + serviceVersion + e); + throw new ProcessToscaArtifactsException( + "An error occurred while trying to parse the Babel artifacts: " + e.getLocalizedMessage()); + } catch (Exception e) { + logger.error(ModelLoaderMsgs.BABEL_REST_REQUEST_ERROR, e, "POST", config.getBabelBaseUrl(), + "Error posting artifact " + artifactInfo.getArtifactName() + " " + serviceVersion + " to Babel: " + + e.getLocalizedMessage()); + throw new ProcessToscaArtifactsException( + "An error occurred while calling the Babel service: " + e.getLocalizedMessage()); + } + } + + private BabelServiceClient createBabelServiceClient(IArtifactInfo artifact, String serviceVersion) + throws ProcessToscaArtifactsException { + BabelServiceClient babelClient; + try { + logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Creating Babel client"); + babelClient = new BabelServiceClient(config); + } catch (Exception e) { + logger.error(ModelLoaderMsgs.BABEL_REST_REQUEST_ERROR, e, "POST", config.getBabelBaseUrl(), + "Error posting artifact " + artifact.getArtifactName() + " " + serviceVersion + " to Babel: " + + e.getLocalizedMessage()); + throw new ProcessToscaArtifactsException( + "An error occurred tyring to convert the tosca artifacts to xml artifacts: " + + e.getLocalizedMessage()); + } + + return babelClient; + } + + private void processModelQuerySpecArtifact(List<Artifact> modelArtifacts, + IDistributionClientDownloadResult downloadResult) throws BabelArtifactParsingException { + logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Processing named query artifact."); + + IModelParser parser = new NamedQueryArtifactParser(); + + List<Artifact> parsedArtifacts = + parser.parse(new String(downloadResult.getArtifactPayload()), downloadResult.getArtifactFilename()); + + if (parsedArtifactsExist(parsedArtifacts)) { + modelArtifacts.addAll(parsedArtifacts); + } else { + throw new BabelArtifactParsingException( + "Could not parse generated XML: " + new String(downloadResult.getArtifactPayload())); + } + } + + private boolean parsedArtifactsExist(List<Artifact> parsedArtifacts) { + return parsedArtifacts != null && !parsedArtifacts.isEmpty(); + } + + private NotificationPublisher getNotificationPublisher() { + if (notificationPublisher == null) { + notificationPublisher = new NotificationPublisher(); + } + + return notificationPublisher; + } + + private BabelArtifactConverter getBabelArtifactConverter() { + if (babelArtifactConverter == null) { + babelArtifactConverter = new BabelArtifactConverter(); + } + + return babelArtifactConverter; + } +} diff --git a/src/main/java/org/onap/aai/modelloader/notification/BabelArtifactConverter.java b/src/main/java/org/onap/aai/modelloader/notification/BabelArtifactConverter.java new file mode 100644 index 0000000..7eb562a --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/notification/BabelArtifactConverter.java @@ -0,0 +1,83 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.notification; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.modelloader.entity.Artifact; +import org.onap.aai.modelloader.entity.catalog.VnfCatalogArtifact; +import org.onap.aai.modelloader.entity.model.BabelArtifactParsingException; +import org.onap.aai.modelloader.entity.model.ModelArtifact; +import org.onap.aai.modelloader.entity.model.ModelArtifactParser; + +/** + * This class is responsible for converting TOSCA artifacts into instances of {@link ModelArtifact} ready for pushing + * the converted artifacts . + */ +class BabelArtifactConverter { + + /** + * This method converts BabelArtifacts into instances of {@link ModelArtifact}. + * + * @param xmlArtifacts xml artifacts to be parsed + * @return List<org.openecomp.modelloader.entity.Artifact> list of converted model artifacts + * @throws BabelArtifactParsingException if an error occurs trying to parse the generated XML files that were + * converted from tosca artifacts + */ + List<Artifact> convertToModel(List<BabelArtifact> xmlArtifacts) throws BabelArtifactParsingException { + Objects.requireNonNull(xmlArtifacts); + List<Artifact> modelArtifacts = new ArrayList<>(); + ModelArtifactParser modelArtParser = new ModelArtifactParser(); + + // Parse TOSCA payloads + for (BabelArtifact xmlArtifact : xmlArtifacts) { + + List<Artifact> parsedArtifacts = modelArtParser.parse(xmlArtifact.getPayload(), xmlArtifact.getName()); + + if (parsedArtifacts == null || parsedArtifacts.isEmpty()) { + throw new BabelArtifactParsingException("Could not parse generated XML: " + xmlArtifact.getPayload()); + } + + modelArtifacts.addAll(parsedArtifacts); + } + + return modelArtifacts; + } + + /** + * This method converts BabelArtifacts into instances of {@link VnfCatalogArtifact}. + * + * @param xmlArtifacts xml artifacts to be parsed + * @return List<org.openecomp.modelloader.entity.Artifact> list of converted catalog artifacts + */ + List<Artifact> convertToCatalog(List<BabelArtifact> xmlArtifacts) { + Objects.requireNonNull(xmlArtifacts); + List<Artifact> catalogArtifacts = new ArrayList<>(); + + for (BabelArtifact xmlArtifact : xmlArtifacts) { + catalogArtifacts.add(new VnfCatalogArtifact(xmlArtifact.getPayload())); + } + + return catalogArtifacts; + } +} diff --git a/src/main/java/org/onap/aai/modelloader/notification/CompDoneStatusMessageBuilder.java b/src/main/java/org/onap/aai/modelloader/notification/CompDoneStatusMessageBuilder.java new file mode 100644 index 0000000..5660ad0 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/notification/CompDoneStatusMessageBuilder.java @@ -0,0 +1,47 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.notification; + +import org.openecomp.sdc.api.IDistributionClient; +import org.openecomp.sdc.api.consumer.IComponentDoneStatusMessage; +import org.openecomp.sdc.api.notification.INotificationData; +import org.openecomp.sdc.utils.DistributionStatusEnum; + +/** + * This class is responsible for building an instance of {@link DistributionStatusMsg}. + */ +public class CompDoneStatusMessageBuilder { + + private CompDoneStatusMessageBuilder() {} + + /** + * Builds an instance of {@link CompDoneStatusMsg} from the given parameters about the status of the + * distribution of the given artifact. + * + * @param client the distribution client this message pertains to + * @param data data about the notification that resulted in this message being created + * @param status the status of the distribution of the artifact to be reported + * @return IComponentDoneStatusMessage implementation of IComponentDoneStatusMessage from the given parameters + */ + public static IComponentDoneStatusMessage build(IDistributionClient client, INotificationData data, DistributionStatusEnum status) { + return new CompDoneStatusMsg(status, data.getDistributionID(), client.getConfiguration().getConsumerID()); + } +} diff --git a/src/main/java/org/onap/aai/modelloader/notification/CompDoneStatusMsg.java b/src/main/java/org/onap/aai/modelloader/notification/CompDoneStatusMsg.java new file mode 100644 index 0000000..db358f3 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/notification/CompDoneStatusMsg.java @@ -0,0 +1,69 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.notification; + +import org.openecomp.sdc.api.consumer.IComponentDoneStatusMessage; +import org.openecomp.sdc.utils.DistributionStatusEnum; + +public class CompDoneStatusMsg implements IComponentDoneStatusMessage { + + private DistributionStatusEnum status; + private String distributionId; + private String consumerId; + + /** + * Creates a new DistributionStatusMsg instance. + * + * @param status - The distribution status to be reported. + * @param distributionId - The identifier of the distribution who's status is being rported on. + * @param consumerId - Identifier of the consumer associated with the distribution. + */ + public CompDoneStatusMsg(DistributionStatusEnum status, String distributionId, String consumerId) { + this.status = status; + this.distributionId = distributionId; + this.consumerId = consumerId; + } + + @Override + public long getTimestamp() { + return System.currentTimeMillis(); + } + + @Override + public DistributionStatusEnum getStatus() { + return status; + } + + @Override + public String getDistributionID() { + return distributionId; + } + + @Override + public String getConsumerID() { + return consumerId; + } + + @Override + public String getComponentName() { + return "AAI"; + } +} diff --git a/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMessageBuilder.java b/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMessageBuilder.java new file mode 100644 index 0000000..fcfd81c --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMessageBuilder.java @@ -0,0 +1,66 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.notification; + +import org.openecomp.sdc.api.IDistributionClient; +import org.openecomp.sdc.api.consumer.IDistributionStatusMessage; +import org.openecomp.sdc.api.notification.IArtifactInfo; +import org.openecomp.sdc.api.notification.INotificationData; +import org.openecomp.sdc.utils.DistributionStatusEnum; + +/** + * This class is responsible for building an instance of {@link DistributionStatusMsg}. + */ +public class DistributionStatusMessageBuilder { + + private DistributionStatusMessageBuilder() {} + + /** + * Builds an instance of {@link DistributionStatusMsg} from the given parameters about the status of the + * distribution of the given artifact. + * + * @param client the distribution client this message pertains to + * @param data data about the notification that resulted in this message being created + * @param artifact the specific artifact to have its distribution status reported on + * @param status the status of the distribution of the artifact to be reported + * @return IDistributionStatusMessage implementation of IDistributionStatusMsg from the given parameters + */ + public static IDistributionStatusMessage build(IDistributionClient client, INotificationData data, + IArtifactInfo artifact, DistributionStatusEnum status) { + return new DistributionStatusMsg(status, data.getDistributionID(), client.getConfiguration().getConsumerID(), + artifact.getArtifactURL()); + } + + /** + * Builds an instance of {@link DistributionStatusMsg} from the given parameters about the status of the + * distribution of the given artifact. + * + * @param client the distribution client this message pertains to + * @param data data about the notification that resulted in this message being created + * @param status the status of the distribution of the artifact to be reported + * @return IDistributionStatusMessage implementation of IDistributionStatusMsg from the given parameters + */ + public static IDistributionStatusMessage build(IDistributionClient client, + INotificationData data, DistributionStatusEnum status) { + return new DistributionStatusMsg(status, data.getDistributionID(), + client.getConfiguration().getConsumerID(), ""); + } +} diff --git a/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMsg.java b/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMsg.java index b4f12a5..cc9fb0b 100644 --- a/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMsg.java +++ b/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMsg.java @@ -24,52 +24,50 @@ import org.openecomp.sdc.api.consumer.IDistributionStatusMessage; import org.openecomp.sdc.utils.DistributionStatusEnum;
public class DistributionStatusMsg implements IDistributionStatusMessage {
- private DistributionStatusEnum status;
- private String distributionId;
- private String consumerId;
- private String artifactUrl;
- /**
- * Creates a new DistributionStatusMsg instance.
- *
- * @param status - The distribution status to be reported.
- * @param distributionId - The identifier of the distribution who's status is being rported on.
- * @param consumerId - Identifier of the consumer associated with the distribution.
- * @param artifactUrl - Resource identifier for the artifact.
- */
- public DistributionStatusMsg(DistributionStatusEnum status,
- String distributionId,
- String consumerId,
- String artifactUrl) {
- this.status = status;
- this.distributionId = distributionId;
- this.consumerId = consumerId;
- this.artifactUrl = artifactUrl;
- }
+ private DistributionStatusEnum status;
+ private String distributionId;
+ private String consumerId;
+ private String artifactUrl;
- @Override
- public long getTimestamp() {
- long currentTimeMillis = System.currentTimeMillis();
- return currentTimeMillis;
- }
+ /**
+ * Creates a new DistributionStatusMsg instance.
+ *
+ * @param status - The distribution status to be reported.
+ * @param distributionId - The identifier of the distribution who's status is being rported on.
+ * @param consumerId - Identifier of the consumer associated with the distribution.
+ * @param artifactUrl - Resource identifier for the artifact.
+ */
+ public DistributionStatusMsg(DistributionStatusEnum status, String distributionId, String consumerId,
+ String artifactUrl) {
+ this.status = status;
+ this.distributionId = distributionId;
+ this.consumerId = consumerId;
+ this.artifactUrl = artifactUrl;
+ }
- @Override
- public DistributionStatusEnum getStatus() {
- return status;
- }
+ @Override
+ public long getTimestamp() {
+ return System.currentTimeMillis();
+ }
- @Override
- public String getDistributionID() {
- return distributionId;
- }
+ @Override
+ public DistributionStatusEnum getStatus() {
+ return status;
+ }
- @Override
- public String getConsumerID() {
- return consumerId;
- }
-
- @Override
- public String getArtifactURL() {
- return artifactUrl;
- }
+ @Override
+ public String getDistributionID() {
+ return distributionId;
+ }
+
+ @Override
+ public String getConsumerID() {
+ return consumerId;
+ }
+
+ @Override
+ public String getArtifactURL() {
+ return artifactUrl;
+ }
}
diff --git a/src/main/java/org/onap/aai/modelloader/notification/DownloadFailureException.java b/src/main/java/org/onap/aai/modelloader/notification/DownloadFailureException.java new file mode 100644 index 0000000..73a191a --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/notification/DownloadFailureException.java @@ -0,0 +1,38 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.notification; + +/** + * Failure to download a distribution. + */ +class DownloadFailureException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + DownloadFailureException(String message) { + super(message); + } +} diff --git a/src/main/java/org/onap/aai/modelloader/notification/EventCallback.java b/src/main/java/org/onap/aai/modelloader/notification/EventCallback.java index fde4826..827ff81 100644 --- a/src/main/java/org/onap/aai/modelloader/notification/EventCallback.java +++ b/src/main/java/org/onap/aai/modelloader/notification/EventCallback.java @@ -20,271 +20,70 @@ */ package org.onap.aai.modelloader.notification; +import java.util.ArrayList; +import java.util.List; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.cl.mdc.MdcContext; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.entity.Artifact; +import org.onap.aai.modelloader.extraction.ArtifactInfoExtractor; +import org.onap.aai.modelloader.service.ModelLoaderMsgs; import org.openecomp.sdc.api.IDistributionClient; -import org.openecomp.sdc.api.consumer.IDistributionStatusMessage; import org.openecomp.sdc.api.consumer.INotificationCallback; import org.openecomp.sdc.api.notification.IArtifactInfo; import org.openecomp.sdc.api.notification.INotificationData; -import org.openecomp.sdc.api.notification.IResourceInstance; -import org.openecomp.sdc.api.results.IDistributionClientDownloadResult; -import org.openecomp.sdc.api.results.IDistributionClientResult; -import org.openecomp.sdc.utils.ArtifactTypeEnum; -import org.openecomp.sdc.utils.DistributionActionResultEnum; -import org.openecomp.sdc.utils.DistributionStatusEnum; -import org.onap.aai.modelloader.config.ModelLoaderConfig; -import org.onap.aai.modelloader.entity.Artifact; -import org.onap.aai.modelloader.entity.catalog.VnfCatalogArtifact; -import org.onap.aai.modelloader.entity.catalog.VnfCatalogArtifactHandler; -import org.onap.aai.modelloader.entity.model.IModelParser; -import org.onap.aai.modelloader.entity.model.ModelArtifactHandler; -import org.onap.aai.modelloader.entity.model.ModelParserFactory; -import org.onap.aai.modelloader.service.ModelLoaderMsgs; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.cl.mdc.MdcContext; -import org.onap.aai.cl.mdc.MdcOverride; import org.slf4j.MDC; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; - public class EventCallback implements INotificationCallback { + private static Logger logger = LoggerFactory.getInstance().getLogger(EventCallback.class.getName()); + private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(EventCallback.class.getName()); - private IDistributionClient client; - private ModelLoaderConfig config; - private static Logger logger = LoggerFactory.getInstance() - .getLogger(EventCallback.class.getName()); - private static Logger auditLogger = LoggerFactory.getInstance() - .getAuditLogger(EventCallback.class.getName()); - private static Logger metricsLogger = LoggerFactory.getInstance() - .getMetricsLogger(EventCallback.class.getName()); - - private static SimpleDateFormat dateFormatter = new SimpleDateFormat( - "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); - - public EventCallback(IDistributionClient client, ModelLoaderConfig config) { - this.client = client; - this.config = config; - } - - @Override - public void activateCallback(INotificationData data) { - // Init MDC - MdcContext.initialize(data.getDistributionID(), "ModelLoader", "", "Event-Bus", ""); - - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, - "Received distribution " + data.getDistributionID()); - - boolean success = true; - List<IArtifactInfo> artifacts = getArtifacts(data); - List<Artifact> modelArtifacts = new ArrayList<Artifact>(); - List<Artifact> catalogArtifacts = new ArrayList<Artifact>(); - - for (IArtifactInfo artifact : artifacts) { - // Grab the current time so we can measure the download time for the - // metrics log - long startTimeInMs = System.currentTimeMillis(); - MdcOverride override = new MdcOverride(); - override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); - - // Download Artifact - IDistributionClientDownloadResult downloadResult = client.download(artifact); - - // Generate metrics log - metricsLogger.info(ModelLoaderMsgs.DOWNLOAD_COMPLETE, null, override, - artifact.getArtifactName(), downloadResult.getDistributionActionResult().toString()); - - if (downloadResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - publishDownloadFailure(data, artifact, downloadResult.getDistributionMessageResult()); - success = false; - break; - } + private ArtifactDeploymentManager artifactDeploymentManager; + private ArtifactDownloadManager artifactDownloadManager; + private IDistributionClient client; + private ModelLoaderConfig config; - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, - "Downloaded artifact: " + artifact.getArtifactName() + " Payload:\n" + new String(downloadResult.getArtifactPayload())); - - publishDownloadSuccess(data, artifact, downloadResult); - - if ((artifact.getArtifactType().compareToIgnoreCase(ArtifactTypeEnum.MODEL_INVENTORY_PROFILE.toString()) == 0) - || (artifact.getArtifactType().compareToIgnoreCase(ArtifactTypeEnum.MODEL_QUERY_SPEC.toString()) == 0)) { - IModelParser parser = ModelParserFactory.createModelParser(downloadResult.getArtifactPayload(), downloadResult.getArtifactName()); - List<Artifact> parsedArtifacts = parser.parse(downloadResult.getArtifactPayload(), downloadResult.getArtifactName()); - if (parsedArtifacts != null && !parsedArtifacts.isEmpty()) { - modelArtifacts.addAll(parsedArtifacts); - } else { - success = false; - publishDeployFailure(data, artifact); - break; - } - } else if (artifact.getArtifactType() - .compareToIgnoreCase(ArtifactTypeEnum.VNF_CATALOG.toString()) == 0) { - catalogArtifacts - .add(new VnfCatalogArtifact(new String(downloadResult.getArtifactPayload()))); - } + public EventCallback(IDistributionClient client, ModelLoaderConfig config) { + this.client = client; + this.config = config; } - String statusString = "SUCCESS"; - if (success) { - ModelArtifactHandler modelHandler = new ModelArtifactHandler(config); - boolean modelDeploySuccess = modelHandler.pushArtifacts(modelArtifacts, - data.getDistributionID()); + @Override + public void activateCallback(INotificationData data) { + MdcContext.initialize(data.getDistributionID(), "ModelLoader", "", "Event-Bus", ""); + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Received distribution " + data.getDistributionID()); - VnfCatalogArtifactHandler catalogHandler = new VnfCatalogArtifactHandler(config); - boolean catalogDeploySuccess = catalogHandler.pushArtifacts(catalogArtifacts, - data.getDistributionID()); + List<IArtifactInfo> artifacts = new ArtifactInfoExtractor().extract(data); + List<Artifact> catalogArtifacts = new ArrayList<>(); + List<Artifact> modelArtifacts = new ArrayList<>(); - for (IArtifactInfo artifact : artifacts) { - if ((artifact.getArtifactType() - .compareToIgnoreCase(ArtifactTypeEnum.MODEL_INVENTORY_PROFILE.toString()) == 0) - || (artifact.getArtifactType() - .compareToIgnoreCase(ArtifactTypeEnum.MODEL_QUERY_SPEC.toString()) == 0)) { - if (modelDeploySuccess) { - publishDeploySuccess(data, artifact); - } else { - publishDeployFailure(data, artifact); - statusString = "FAILURE"; - } - } else if (artifact.getArtifactType() - .compareToIgnoreCase(ArtifactTypeEnum.VNF_CATALOG.toString()) == 0) { - if (catalogDeploySuccess) { - publishDeploySuccess(data, artifact); - } else { - publishDeployFailure(data, artifact); - statusString = "FAILURE"; - } - } - } - } else { - statusString = "FAILURE"; - } + boolean success = getArtifactDownloadManager() + .downloadArtifacts(data, artifacts, modelArtifacts, catalogArtifacts); - auditLogger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, - "Processed distribution " + data.getDistributionID() + " (" + statusString + ")"); - MDC.clear(); - } - - private List<IArtifactInfo> getArtifacts(INotificationData data) { - List<IArtifactInfo> artifacts = new ArrayList<IArtifactInfo>(); - List<IResourceInstance> resources = data.getResources(); - - if (data.getServiceArtifacts() != null) { - artifacts.addAll(data.getServiceArtifacts()); - } - - if (resources != null) { - for (IResourceInstance resource : resources) { - if (resource.getArtifacts() != null) { - artifacts.addAll(resource.getArtifacts()); + if (success) { + success = getArtifactDeploymentManager().deploy(data, artifacts, modelArtifacts, catalogArtifacts); } - } - } - - return artifacts; - } - - private void publishDownloadFailure(INotificationData data, IArtifactInfo artifact, - String errorMessage) { - // Grab the current time so we can measure the download time for the metrics - // log - long startTimeInMs = System.currentTimeMillis(); - MdcOverride override = new MdcOverride(); - override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); - - IDistributionClientResult sendDownloadStatus = client.sendDownloadStatus( - buildStatusMessage(client, data, artifact, DistributionStatusEnum.DOWNLOAD_ERROR)); - metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "download failure", - artifact.getArtifactName(), sendDownloadStatus.getDistributionActionResult().toString()); - - if (sendDownloadStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, - "Failed to publish download failure status: " - + sendDownloadStatus.getDistributionMessageResult()); - } - - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, - "Failed to download artifact " + artifact.getArtifactName() + ": " + errorMessage); - } - - private void publishDownloadSuccess(INotificationData data, IArtifactInfo artifact, - IDistributionClientDownloadResult downloadResult) { - // Grab the current time so we can measure the download time for the metrics - // log - long startTimeInMs = System.currentTimeMillis(); - MdcOverride override = new MdcOverride(); - override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); - - IDistributionClientResult sendDownloadStatus = client.sendDownloadStatus( - buildStatusMessage(client, data, artifact, DistributionStatusEnum.DOWNLOAD_OK)); - metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "download success", - artifact.getArtifactName(), sendDownloadStatus.getDistributionActionResult().toString()); - if (sendDownloadStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, - "Failed to publish download success status: " - + sendDownloadStatus.getDistributionMessageResult()); + String statusString = success ? "SUCCESS" : "FAILURE"; + auditLogger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + "Processed distribution " + data.getDistributionID() + " (" + statusString + ")"); + MDC.clear(); } - if (logger.isDebugEnabled()) { - StringBuilder sb = new StringBuilder(); - sb.append("Downloaded artifact:\n"); - sb.append("ArtInfo_Art_Name: " + artifact.getArtifactName()); - sb.append("\nArtInfo_Art_description: " + artifact.getArtifactDescription()); - sb.append("\nArtInfo_Art_CheckSum: " + artifact.getArtifactChecksum()); - sb.append("\nArtInfo_Art_Url: " + artifact.getArtifactURL()); - sb.append("\nArtInfo_Art_Type: " + artifact.getArtifactType()); - sb.append("\nArtInfo_Serv_description: " + data.getServiceDescription()); - sb.append("\nArtInfo_Serv_Name: " + data.getServiceName()); - sb.append("\nGet_serviceVersion: " + data.getServiceVersion()); - sb.append("\nGet_Service_UUID: " + data.getServiceUUID()); - sb.append("\nArtInfo_DistributionId: " + data.getDistributionID()); - logger.debug(sb.toString()); - } - } - - private void publishDeployFailure(INotificationData data, IArtifactInfo artifact) { - // Grab the current time so we can measure the download time for the metrics - // log - long startTimeInMs = System.currentTimeMillis(); - MdcOverride override = new MdcOverride(); - override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); - - IDistributionClientResult sendStatus = client.sendDeploymentStatus( - buildStatusMessage(client, data, artifact, DistributionStatusEnum.DEPLOY_ERROR)); - metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "deploy failure", - artifact.getArtifactName(), sendStatus.getDistributionActionResult().toString()); + private ArtifactDeploymentManager getArtifactDeploymentManager() { + if (artifactDeploymentManager == null) { + artifactDeploymentManager = new ArtifactDeploymentManager(client, config); + } - if (sendStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, - "Failed to publish deploy failure status: " + sendStatus.getDistributionMessageResult()); + return artifactDeploymentManager; } - } - - private void publishDeploySuccess(INotificationData data, IArtifactInfo artifact) { - // Grab the current time so we can measure the download time for the metrics - // log - long startTimeInMs = System.currentTimeMillis(); - MdcOverride override = new MdcOverride(); - override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs)); - IDistributionClientResult sendStatus = client.sendDownloadStatus( - buildStatusMessage(client, data, artifact, DistributionStatusEnum.DEPLOY_OK)); - metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "deploy success", - artifact.getArtifactName(), sendStatus.getDistributionActionResult().toString()); + private ArtifactDownloadManager getArtifactDownloadManager() { + if (artifactDownloadManager == null) { + artifactDownloadManager = new ArtifactDownloadManager(client, config); + } - if (sendStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, - "Failed to publish deploy success status: " + sendStatus.getDistributionMessageResult()); + return artifactDownloadManager; } - } - - private IDistributionStatusMessage buildStatusMessage(IDistributionClient client, - INotificationData data, IArtifactInfo artifact, DistributionStatusEnum status) { - IDistributionStatusMessage statusMessage = new DistributionStatusMsg(status, - data.getDistributionID(), client.getConfiguration().getConsumerID(), - artifact.getArtifactURL()); - - return statusMessage; - } - } diff --git a/src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java b/src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java new file mode 100644 index 0000000..447e817 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/notification/NotificationPublisher.java @@ -0,0 +1,228 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.notification; + +import java.io.FileInputStream; +import java.io.IOException; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Properties; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.cl.mdc.MdcContext; +import org.onap.aai.cl.mdc.MdcOverride; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.service.ModelLoaderMsgs; +import org.openecomp.sdc.api.IDistributionClient; +import org.openecomp.sdc.api.notification.IArtifactInfo; +import org.openecomp.sdc.api.notification.INotificationData; +import org.openecomp.sdc.api.results.IDistributionClientResult; +import org.openecomp.sdc.utils.DistributionActionResultEnum; +import org.openecomp.sdc.utils.DistributionStatusEnum; + +/** + * This class is responsible for publishing the status of actions performed working with artifacts. + */ +class NotificationPublisher { + + private static Logger logger = LoggerFactory.getInstance().getLogger(NotificationPublisher.class); + private static Logger metricsLogger = LoggerFactory.getInstance().getMetricsLogger(NotificationPublisher.class); + + protected static final String FILESEP = + (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); + protected static final String CONFIG_DIR = System.getProperty("CONFIG_HOME") + FILESEP; + protected static final String CONFIG_AUTH_LOCATION = CONFIG_DIR + "auth" + FILESEP; + protected static final String CONFIG_FILE = CONFIG_DIR + "model-loader.properties"; + + private boolean publishingEnabled; + + public NotificationPublisher() { + Properties configProperties = new Properties(); + try { + configProperties.load(new FileInputStream(CONFIG_FILE)); + } catch (IOException e) { + String errorMsg = "Failed to load configuration: " + e.getMessage(); + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, e, errorMsg); + } + + ModelLoaderConfig config = new ModelLoaderConfig(configProperties, CONFIG_AUTH_LOCATION); + + publishingEnabled = !config.getASDCConnectionDisabled(); + } + + /** + * This method is responsible for publishing notification that the download of an artifact failed. + * + * @param client The distribution client this notification relates to + * @param data data about the notification that resulted in this message being created + * @param artifact the specific artifact to have its distribution status reported on + * @param errorMessage the error message that is to be reported + */ + void publishDownloadFailure(IDistributionClient client, INotificationData data, IArtifactInfo artifact, + String errorMessage) { + publishDownloadStatus(DistributionStatusEnum.DOWNLOAD_ERROR, client, data, artifact, "failure"); + + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Failed to download artifact " + artifact.getArtifactName() + ": " + errorMessage); + } + + private void publishDownloadStatus(DistributionStatusEnum distributionStatusEnum, IDistributionClient client, + INotificationData data, IArtifactInfo artifact, String result) { + if (publishingEnabled) { + MdcOverride override = initMDCStartTime(); + + IDistributionClientResult sendDownloadStatus = client.sendDownloadStatus( + DistributionStatusMessageBuilder.build(client, data, artifact, distributionStatusEnum)); + metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "download " + result, + artifact.getArtifactName(), sendDownloadStatus.getDistributionActionResult().toString()); + + if (sendDownloadStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Failed to publish download " + result + + " status: " + sendDownloadStatus.getDistributionMessageResult()); + } + } else { + logPublishingDisabled(distributionStatusEnum.toString(), result); + } + } + + private MdcOverride initMDCStartTime() { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + MdcOverride override = new MdcOverride(); + + override.addAttribute(MdcContext.MDC_START_TIME, ZonedDateTime.now().format(formatter)); + + return override; + } + + /** + * This method is responsible for publishing notification that the download of an artifact was successful. + * + * @param client The distribution client this notification relates to + * @param data data about the notification that resulted in this message being created + * @param artifact the specific artifact to have its distribution status reported on + */ + void publishDownloadSuccess(IDistributionClient client, INotificationData data, IArtifactInfo artifact) { + publishDownloadStatus(DistributionStatusEnum.DOWNLOAD_OK, client, data, artifact, "success"); + + if (logger.isDebugEnabled()) { + // @formatter:off + String msg = "Downloaded artifact:\n" + + "ArtInfo_Art_Name: " + artifact.getArtifactName() + + "\nArtInfo_Art_description: " + artifact.getArtifactDescription() + + "\nArtInfo_Art_CheckSum: " + artifact.getArtifactChecksum() + + "\nArtInfo_Art_Url: " + artifact.getArtifactURL() + + "\nArtInfo_Art_Type: " + artifact.getArtifactType() + + "\nArtInfo_Serv_description: " + data.getServiceDescription() + + "\nArtInfo_Serv_Name: " + data.getServiceName() + + "\nGet_serviceVersion: " + data.getServiceVersion() + + "\nGet_Service_UUID: " + data.getServiceUUID() + + "\nArtInfo_DistributionId: " + data.getDistributionID(); + logger.debug(msg); + // @formatter:on + } + } + + /** + * This method is responsible for publishing notification that the deployment of an artifact failed. + * + * @param client The distribution client this notification relates to + * @param data data about the notification that resulted in this message being created + * @param artifact the specific artifact to have its deployment status reported on + */ + void publishDeployFailure(IDistributionClient client, INotificationData data, IArtifactInfo artifact) { + publishDeployStatus(client, data, artifact, DistributionStatusEnum.DEPLOY_ERROR, "failure"); + } + + private void publishDeployStatus(IDistributionClient client, INotificationData data, IArtifactInfo artifact, + DistributionStatusEnum distributionStatusEnum, String result) { + if (publishingEnabled) { + MdcOverride override = initMDCStartTime(); + + IDistributionClientResult sendStatus = client.sendDeploymentStatus( + DistributionStatusMessageBuilder.build(client, data, artifact, distributionStatusEnum)); + metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "deploy " + result, + artifact.getArtifactName(), sendStatus.getDistributionActionResult().toString()); + + if (sendStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Failed to publish deploy " + result + " status: " + sendStatus.getDistributionMessageResult()); + } + } else { + logPublishingDisabled(distributionStatusEnum.toString(), result); + } + } + + /** + * This method is responsible for publishing notification that the deployment of an artifact was succesful. + * + * @param client The distribution client this notification relates to + * @param data data about the notification that resulted in this message being created + * @param artifact the specific artifact to have its deployment status reported on + */ + void publishDeploySuccess(IDistributionClient client, INotificationData data, IArtifactInfo artifact) { + publishDeployStatus(client, data, artifact, DistributionStatusEnum.DEPLOY_OK, "success"); + } + + void publishComponentSuccess(IDistributionClient client, INotificationData data) { + if (publishingEnabled) { + MdcOverride override = initMDCStartTime(); + + IDistributionClientResult sendStatus = client.sendComponentDoneStatus( + CompDoneStatusMessageBuilder.build(client, data, DistributionStatusEnum.COMPONENT_DONE_OK)); + + metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "component done ok", "all", + sendStatus.getDistributionActionResult().toString()); + + if (sendStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Failed to publish component done ok: " + sendStatus.getDistributionMessageResult()); + } + } else { + logPublishingDisabled(DistributionStatusEnum.COMPONENT_DONE_OK.toString(), null); + } + } + + void publishComponentFailure(IDistributionClient client, INotificationData data, String errorReason) { + if (publishingEnabled) { + MdcOverride override = initMDCStartTime(); + + IDistributionClientResult sendStatus = client.sendComponentDoneStatus( + CompDoneStatusMessageBuilder.build(client, data, DistributionStatusEnum.COMPONENT_DONE_ERROR), + errorReason); + + metricsLogger.info(ModelLoaderMsgs.EVENT_PUBLISHED, null, override, "component done error", "all", + sendStatus.getDistributionActionResult().toString()); + + if (sendStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, + "Failed to publish component done error: " + sendStatus.getDistributionMessageResult()); + } + } else { + logPublishingDisabled(DistributionStatusEnum.COMPONENT_DONE_ERROR.toString(), errorReason); + } + } + + private void logPublishingDisabled(String statusType, String message) { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, + "Notification publishing is disabled, skipping publishing of the following status: " + statusType + + " with message: " + message); + } +} diff --git a/src/main/java/org/onap/aai/modelloader/notification/ProcessToscaArtifactsException.java b/src/main/java/org/onap/aai/modelloader/notification/ProcessToscaArtifactsException.java new file mode 100644 index 0000000..6678af6 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/notification/ProcessToscaArtifactsException.java @@ -0,0 +1,35 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.notification; + +public class ProcessToscaArtifactsException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + public ProcessToscaArtifactsException(String message) { + super(message); + } +} diff --git a/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java b/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java index 08d1417..7d2ab09 100644 --- a/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java +++ b/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java @@ -20,461 +20,192 @@ */ package org.onap.aai.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.onap.aai.modelloader.config.ModelLoaderConfig; -import org.onap.aai.modelloader.restclient.AaiRestClient; -import org.onap.aai.modelloader.service.ModelLoaderMsgs; -import org.onap.aai.cl.api.LogFields; -import org.onap.aai.cl.api.LogLine; +import com.sun.jersey.core.util.MultivaluedMapImpl; // NOSONAR +// import edu.emory.mathcs.backport.java.util.Collections; +import java.io.IOException; +import java.io.StringReader; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.cl.mdc.MdcContext; -import org.onap.aai.cl.mdc.MdcOverride; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.service.ModelLoaderMsgs; +import org.onap.aai.restclient.client.OperationResult; +import org.onap.aai.restclient.client.RestClient; +import org.onap.aai.restclient.enums.RestAuthenticationMode; 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; - +/** + * Wrapper around the standard A&AI Rest Client interface. This currently uses Jersey client 1.x + * + */ 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(); + public static final String HEADER_TRANS_ID = "X-TransactionId"; + public static final String HEADER_FROM_APP_ID = "X-FromAppId"; + public static final String ML_APP_NAME = "ModelLoader"; + private static final String RESOURCE_VERSION_PARAM = "resource-version"; - try { - Client client = setupClient(); + private static Logger logger = LoggerFactory.getInstance().getLogger(AaiRestClient.class.getName()); - baos = new ByteArrayOutputStream(); - PrintStream ps = new PrintStream(baos); - if (logger.isDebugEnabled()) { - client.addFilter(new LoggingFilter(ps)); - } + private ModelLoaderConfig config = null; - // 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); + public AaiRestClient(ModelLoaderConfig config) { + this.config = config; } - 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()); - } + /** + * Send a GET request to the A&AI for a resource. + * + * @param url + * @param transId + * @param mediaType + * @return + */ + public OperationResult getResource(String url, String transId, MediaType mediaType) { + return setupClient().get(url, buildHeaders(transId), mediaType); } - 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()); - } + /** + * Send a PUT request to the A&AI. + * + * @param url - the url + * @param payload - the XML or JSON payload for the request + * @param transId - transaction ID + * @param mediaType - the content type (XML or JSON) + * @return operation result + */ + public OperationResult putResource(String url, String payload, String transId, MediaType mediaType) { + logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_PAYLOAD, payload); + return setupClient().put(url, payload, buildHeaders(transId), mediaType, mediaType); } - 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()); - } + /** + * 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 OperationResult postResource(String url, String payload, String transId, MediaType mediaType) { + logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_PAYLOAD, payload); + return setupClient().post(url, payload, buildHeaders(transId), mediaType, mediaType); } - 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; + /** + * 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 OperationResult deleteResource(String url, String resourceVersion, String transId) { + URI uri = UriBuilder.fromUri(url).queryParam(RESOURCE_VERSION_PARAM, resourceVersion).build(); + return setupClient().delete(uri.toString(), buildHeaders(transId), null); } - // 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; + /** + * 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 OperationResult getAndDeleteResource(String url, String transId) { + // First, GET the model + OperationResult getResponse = getResource(url, transId, MediaType.APPLICATION_XML_TYPE); + if ((getResponse == null) || (getResponse.getResultCode() != 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); } - 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); + public boolean useBasicAuth() { + return (config.getAaiAuthenticationUser() != null) && (config.getAaiAuthenticationPassword() != null); + } - return client; - } + private RestClient setupClient() { + RestClient restClient = new RestClient(); - private String getResourceVersion(ClientResponse response) - throws ParserConfigurationException, SAXException, IOException { - String respData = response.getEntity(String.class); + // @formatter:off + restClient.validateServerHostname(false) + .validateServerCertChain(false) + .clientCertFile(config.getAaiKeyStorePath()) + .clientCertPassword(config.getAaiKeyStorePassword()); + // @formatter:on - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - InputSource is = new InputSource(new StringReader(respData)); - Document doc = builder.parse(is); + if (useBasicAuth()) { + restClient.authenticationMode(RestAuthenticationMode.SSL_BASIC); + restClient.basicAuthUsername(config.getAaiAuthenticationUser()); + restClient.basicAuthPassword(config.getAaiAuthenticationPassword()); + } - 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 restClient; } - return null; - } - - private String getAuthenticationCredentials() { - - String usernameAndPassword = config.getAaiAuthenticationUser() + ":" - + config.getAaiAuthenticationPassword(); - return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes()); - } + /** + * Create the HTTP headers required for an A&AI operation (GET/POST/PUT/DELETE) + * + * @param transId + * @return map of headers + */ + @SuppressWarnings("unchecked") + private Map<String, List<String>> buildHeaders(String transId) { + MultivaluedMap<String, String> headers = new MultivaluedMapImpl(); + headers.put(HEADER_TRANS_ID, Collections.singletonList(transId)); + headers.put(HEADER_FROM_APP_ID, Collections.singletonList(ML_APP_NAME)); + return headers; + } - public boolean useBasicAuth() { - return (config.getAaiAuthenticationUser() != null) - && (config.getAaiAuthenticationPassword() != null); - } + private String getResourceVersion(OperationResult getResponse) + throws ParserConfigurationException, SAXException, IOException { + String respData = getResponse.getResult(); + + 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(respData)); + Document doc = builder.parse(is); + + NodeList nodesList = doc.getDocumentElement().getChildNodes(); + + // @formatter:off + return IntStream.range(0, nodesList.getLength()).mapToObj(nodesList::item) + .filter(childNode -> childNode.getNodeName().equals(RESOURCE_VERSION_PARAM)) + .findFirst() + .map(Node::getTextContent) + .orElse(null); + // @formatter:on + } } diff --git a/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClient.java b/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClient.java new file mode 100644 index 0000000..a861580 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/restclient/BabelServiceClient.java @@ -0,0 +1,184 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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.restclient; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.google.json.JsonSanitizer; +import com.sun.jersey.api.client.Client; // NOSONAR +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Base64; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javax.ws.rs.core.Response; +import org.json.JSONObject; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.service.ModelLoaderMsgs; + +/** + * Initial version for testing End to End scenarios + * + */ +public class BabelServiceClient { + + private static Logger logger = LoggerFactory.getInstance().getLogger(BabelServiceClient.class); + + private static final String SSL_PROTOCOL = "TLS"; + private static final String KEYSTORE_ALGORITHM = "SunX509"; + private static final String KEYSTORE_TYPE = "PKCS12"; + + private ModelLoaderConfig config; + private Client client; + + private TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; // NOSONAR + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + // Do nothing + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + // Do nothing + } + }}; + + public class BabelServiceException extends Exception { + + /** + * Babel Service error response + */ + private static final long serialVersionUID = 1L; + + public BabelServiceException(String message) { + super(message); + } + + } + + /** + * @param config + * @throws NoSuchAlgorithmException + * @throws KeyStoreException + * @throws CertificateException + * @throws IOException + * @throws UnrecoverableKeyException + * @throws KeyManagementException + */ + public BabelServiceClient(ModelLoaderConfig config) throws NoSuchAlgorithmException, KeyStoreException, + CertificateException, IOException, UnrecoverableKeyException, KeyManagementException { + this.config = config; + + logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Creating Babel Service client"); + + SSLContext ctx = SSLContext.getInstance(SSL_PROTOCOL); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM); + KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE); + + String clientCertPassword = config.getBabelKeyStorePassword(); + + char[] pwd = null; + if (clientCertPassword != null) { + pwd = clientCertPassword.toCharArray(); + } + + String clientCertFileName = config.getBabelKeyStorePath(); + if (clientCertFileName != null) { + FileInputStream fin = new FileInputStream(clientCertFileName); + ks.load(fin, pwd); + kmf.init(ks, pwd); + ctx.init(kmf.getKeyManagers(), trustAllCerts, null); + } else { + ctx.init(null, trustAllCerts, null); + } + + logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Initialised context"); + + HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); + HttpsURLConnection.setDefaultHostnameVerifier((host, session) -> true); + + client = Client.create(new DefaultClientConfig()); + + logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Jersey client created"); + } + + /** + * @param artifactPayload + * @param artifactName + * @param artifactVersion + * @param transactionId + * @return + * @throws BabelServiceException + */ + public List<BabelArtifact> postArtifact(byte[] artifactPayload, String artifactName, String artifactVersion, + String transactionId) throws BabelServiceException { + Objects.requireNonNull(artifactPayload); + + String encodedPayload = Base64.getEncoder().encodeToString(artifactPayload); + + JSONObject obj = new JSONObject(); + obj.put("csar", encodedPayload); + obj.put("artifactVersion", artifactVersion); + obj.put("artifactName", artifactName); + + logger.info(ModelLoaderMsgs.BABEL_REST_REQUEST_PAYLOAD, " Artifact Name: " + artifactName + + " Artifact version: " + artifactVersion + " Artifact payload: " + encodedPayload); + + WebResource webResource = client.resource(config.getBabelBaseUrl() + config.getBabelGenerateArtifactsUrl()); + ClientResponse response = webResource.type("application/json") + .header(AaiRestClient.HEADER_TRANS_ID, Collections.singletonList(transactionId)) + .header(AaiRestClient.HEADER_FROM_APP_ID, Collections.singletonList(AaiRestClient.ML_APP_NAME)) + .post(ClientResponse.class, obj.toString()); + String sanitizedJson = JsonSanitizer.sanitize(response.getEntity(String.class)); + + logger.debug(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Babel response " + response.getStatus() + " " + sanitizedJson); + + if (response.getStatus() != Response.Status.OK.getStatusCode()) { + throw new BabelServiceException(sanitizedJson); + } + + return new Gson().fromJson(sanitizedJson, new TypeToken<List<BabelArtifact>>() {}.getType()); + } +} diff --git a/src/main/java/org/onap/aai/modelloader/service/ArtifactInfoImpl.java b/src/main/java/org/onap/aai/modelloader/service/ArtifactInfoImpl.java new file mode 100644 index 0000000..e32d92c --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/service/ArtifactInfoImpl.java @@ -0,0 +1,134 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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 java.util.Collections; +import org.openecomp.sdc.api.notification.IArtifactInfo; + +/** + * This class is an implementation of IArtifactInfo for test purposes. + */ +public class ArtifactInfoImpl implements IArtifactInfo { + + private java.lang.String artifactName; + private java.lang.String artifactType; + private java.lang.String artifactDescription; + private java.lang.String artifactVersion; + + @Override + public String getArtifactName() { + return artifactName; + } + + public void setArtifactName(String artifactName) { + this.artifactName = artifactName; + } + + @Override + public String getArtifactType() { + return artifactType; + } + + public void setArtifactType(String artifactType) { + this.artifactType = artifactType; + } + + @Override + public String getArtifactURL() { + return null; + } + + @Override + public String getArtifactChecksum() { + return null; + } + + @Override + public String getArtifactDescription() { + return artifactDescription; + } + + public void setArtifactDescription(String artifactDescription) { + this.artifactDescription = artifactDescription; + } + + @Override + public Integer getArtifactTimeout() { + return null; + } + + @Override + public String getArtifactVersion() { + return artifactVersion; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + @Override + public String getArtifactUUID() { + return null; + } + + @Override + public IArtifactInfo getGeneratedArtifact() { + return null; + } + + @Override + public java.util.List<org.openecomp.sdc.api.notification.IArtifactInfo> getRelatedArtifacts() { + return Collections.emptyList(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ArtifactInfoImpl that = (ArtifactInfoImpl) o; + + if (artifactName != null ? !artifactName.equals(that.artifactName) : that.artifactName != null) { + return false; + } + if (artifactType != null ? !artifactType.equals(that.artifactType) : that.artifactType != null) { + return false; + } + if (artifactDescription != null ? !artifactDescription.equals(that.artifactDescription) + : that.artifactDescription != null) { + return false; + } + return artifactVersion != null ? artifactVersion.equals(that.artifactVersion) : that.artifactVersion == null; + } + + @Override + public int hashCode() { + int result = artifactName != null ? artifactName.hashCode() : 0; + result = 31 * result + (artifactType != null ? artifactType.hashCode() : 0); + result = 31 * result + (artifactDescription != null ? artifactDescription.hashCode() : 0); + result = 31 * result + (artifactVersion != null ? artifactVersion.hashCode() : 0); + return result; + } +} diff --git a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java index 56ffe63..1b466c8 100644 --- a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java +++ b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java @@ -21,8 +21,6 @@ package org.onap.aai.modelloader.service;
import java.io.IOException;
-
-import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@@ -30,24 +28,22 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
public interface ModelLoaderInterface {
- @GET
- @Path("/loadModel/{modelid}")
- public Response loadModel(@PathParam("modelid") String modelid);
+ @GET
+ @Path("/loadModel/{modelid}")
+ public Response loadModel(@PathParam("modelid") String modelid);
- @PUT
- @Path("/saveModel/{modelid}/{modelname}")
- public Response saveModel(@PathParam("modelid") String modelid,
- @PathParam("modelname") String modelname);
+ @PUT
+ @Path("/saveModel/{modelid}/{modelname}")
+ public Response saveModel(@PathParam("modelid") String modelid, @PathParam("modelname") String modelname);
- @POST
- @Consumes("application/xml")
- @Produces("application/xml")
- @Path("/ingestModel/{modelid}")
- public Response ingestModel(@PathParam("modelid") String modelid, @Context HttpServletRequest req,
- String payload) throws IOException;
+ @POST
+ @Consumes("text/plain")
+ @Produces("application/xml")
+ @Path("/ingestModel/{modelName}/{modelVersion}")
+ public Response ingestModel(@PathParam("modelName") String modelid, @PathParam("modelVersion") String modelVersion,
+ String payload) throws IOException;
}
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 f8f04fa..ad17a43 100644 --- a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderMsgs.java +++ b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderMsgs.java @@ -21,88 +21,100 @@ 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} = artifact name
- */
- ARTIFACT_PARSE_ERROR,
-
- /**
- * Arguments: {0} = artifact name.
- * {1} = result.
- */
- DOWNLOAD_COMPLETE,
-
- /**
- * Arguments: {0} = event.
- * {1} = artifact name.
- * {2} = result.
- */
- EVENT_PUBLISHED;
-
- /**
- * Load message bundle (ModelLoaderMsgs.properties file)
- */
- static {
- EELFResourceManager.loadMessageBundle("org/openecomp/modelloader/service/ModelLoaderMsgs");
- }
+ /**
+ * 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");
+ }
}
diff --git a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java index edab788..aa3481c 100644 --- a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java +++ b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java @@ -20,182 +20,210 @@ */ package org.onap.aai.modelloader.service; -import org.openecomp.sdc.api.IDistributionClient; -import org.openecomp.sdc.api.results.IDistributionClientResult; -import org.openecomp.sdc.impl.DistributionClientFactory; -import org.openecomp.sdc.utils.DistributionActionResultEnum; -import org.onap.aai.modelloader.config.ModelLoaderConfig; -import org.onap.aai.modelloader.entity.model.ModelArtifactHandler; -import org.onap.aai.modelloader.notification.EventCallback; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; - import java.io.FileInputStream; import java.io.IOException; +import java.util.ArrayList; +import java.util.Base64; import java.util.Date; +import java.util.List; import java.util.Properties; import java.util.Timer; import java.util.TimerTask; -import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Response; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.entity.Artifact; +import org.onap.aai.modelloader.notification.ArtifactDeploymentManager; +import org.onap.aai.modelloader.notification.ArtifactDownloadManager; +import org.onap.aai.modelloader.notification.EventCallback; +import org.openecomp.sdc.api.IDistributionClient; +import org.openecomp.sdc.api.notification.IArtifactInfo; +import org.openecomp.sdc.api.notification.INotificationData; +import org.openecomp.sdc.api.results.IDistributionClientResult; +import org.openecomp.sdc.impl.DistributionClientFactory; +import org.openecomp.sdc.utils.DistributionActionResultEnum; + /** - * Service class in charge of managing the negotiating model loading - * capabilities between AAI and an ASDC. + * Service class in charge of managing the negotiating model loading capabilities between AAI and an ASDC. */ public class ModelLoaderService implements ModelLoaderInterface { - - protected static final String FILESEP = (System.getProperty("file.separator") == null) ? "/" - : System.getProperty("file.separator"); - - protected static final String CONFIG_DIR = System.getProperty("CONFIG_HOME") + FILESEP; - protected static final String CONFIG_AUTH_LOCATION = CONFIG_DIR + "auth" + FILESEP; - protected static final String CONFIG_FILE = CONFIG_DIR + "model-loader.properties"; - - private IDistributionClient client; - private ModelLoaderConfig config; - private Timer timer = null; - - static Logger logger = LoggerFactory.getInstance().getLogger(ModelLoaderService.class.getName()); - - /** - * Responsible for loading configuration files and calling initialization. - */ - public ModelLoaderService() { - start(); - } - - protected void start() { - // Load model loader system configuration - logger.info(ModelLoaderMsgs.LOADING_CONFIGURATION); - Properties configProperties = new Properties(); - try { - configProperties.load(new FileInputStream(CONFIG_FILE)); - } catch (IOException e) { - String errorMsg = "Failed to load configuration: " + e.getMessage(); - logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); - shutdown(); - } - - config = new ModelLoaderConfig(configProperties, CONFIG_AUTH_LOCATION); - init(); - - Runtime.getRuntime().addShutdownHook(new Thread(new Runnable(){ - public void run() { - preShutdownOperations(); - } - })); - } - - /** - * Responsible for stopping the connection to the distribution client before - * the resource is destroyed. - */ - protected void preShutdownOperations() { - logger.info(ModelLoaderMsgs.STOPPING_CLIENT); - if (client != null) { - client.stop(); - } - } - - /** - * Responsible for loading configuration files, initializing model - * distribution clients, and starting them. - */ - protected void init() { - // Initialize distribution client - logger.debug(ModelLoaderMsgs.INITIALIZING, "Initializing distribution client..."); - client = DistributionClientFactory.createDistributionClient(); - EventCallback callback = new EventCallback(client, config); - - IDistributionClientResult initResult = client.init(config, callback); - - if (initResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - String errorMsg = "Failed to initialize distribution client: " - + initResult.getDistributionMessageResult(); - logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); - - // Kick off a timer to retry the SDC connection - timer = new Timer(); - TimerTask task = new SdcConnectionJob(client, config, callback, timer); - timer.schedule(task, new Date(), 60000); - } - else { - // Start distribution client - logger.debug(ModelLoaderMsgs.INITIALIZING, "Starting distribution client..."); - IDistributionClientResult startResult = client.start(); - if (startResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - String errorMsg = "Failed to start distribution client: " - + startResult.getDistributionMessageResult(); - logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); - - // Kick off a timer to retry the SDC connection - timer = new Timer(); - TimerTask task = new SdcConnectionJob(client, config, callback, timer); - timer.schedule(task, new Date(), 60000); - } - else { - logger.info(ModelLoaderMsgs.INITIALIZING, "Connection to SDC established"); - } - } - } - - /** - * Shut down the process. - */ - private void shutdown() { - preShutdownOperations(); - - // TODO: Find a better way to shut down the model loader. - try { - // Give logs time to write to file - Thread.sleep(2000); - } catch (InterruptedException e) { - // Nothing we can do at this point - } - - Runtime.getRuntime().halt(1); - } - - /** (non-Javadoc) - * @see org.onap.aai.modelloader.service.ModelLoaderInterface#loadModel(java.lang.String) - */ - @Override - public Response loadModel(String modelid) { - Response response = Response.ok("{\"model_loaded\":\"" + modelid + "\"}").build(); - - return response; - } - - /** (non-Javadoc) - * @see org.onap.aai.modelloader.service.ModelLoaderInterface#saveModel(java.lang.String, java.lang.String) - */ - @Override - public Response saveModel(String modelid, String modelname) { - Response response = Response.ok("{\"model_saved\":\"" + modelid + "-" + modelname + "\"}") - .build(); - - return response; - } - - @Override - public Response ingestModel(String modelid, HttpServletRequest req, String payload) - throws IOException { - Response response; - - if (config.getIngestSimulatorEnabled()) { - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Received test artifact"); - - ModelArtifactHandler handler = new ModelArtifactHandler(config); - handler.loadModelTest(payload.getBytes()); - - response = Response.ok().build(); - } else { - logger.debug("Simulation interface disabled"); - response = Response.serverError().build(); - } - - return response; - } + + protected static final String FILESEP = + (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); + + protected static final String CONFIG_DIR = System.getProperty("CONFIG_HOME") + FILESEP; + protected static final String CONFIG_AUTH_LOCATION = CONFIG_DIR + "auth" + FILESEP; + protected static final String CONFIG_FILE = CONFIG_DIR + "model-loader.properties"; + + private IDistributionClient client; + private ModelLoaderConfig config; + + static Logger logger = LoggerFactory.getInstance().getLogger(ModelLoaderService.class.getName()); + + /** + * Responsible for loading configuration files and calling initialization. + */ + public ModelLoaderService() { + start(); + } + + protected void start() { + // Load model loader system configuration + logger.info(ModelLoaderMsgs.LOADING_CONFIGURATION); + Properties configProperties = new Properties(); + try { + configProperties.load(new FileInputStream(CONFIG_FILE)); + } catch (IOException e) { + String errorMsg = "Failed to load configuration: " + e.getMessage(); + logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); + shutdown(); + } + + config = new ModelLoaderConfig(configProperties, CONFIG_AUTH_LOCATION); + init(); + + Runtime.getRuntime().addShutdownHook(new Thread(this::preShutdownOperations)); + } + + /** + * Responsible for stopping the connection to the distribution client before the resource is destroyed. + */ + protected void preShutdownOperations() { + logger.info(ModelLoaderMsgs.STOPPING_CLIENT); + if (client != null) { + client.stop(); + } + } + + /** + * Responsible for loading configuration files, initializing model distribution clients, and starting them. + */ + protected void init() { + if (!config.getASDCConnectionDisabled()) { + // Initialize distribution client + logger.debug(ModelLoaderMsgs.INITIALIZING, "Initializing distribution client..."); + client = DistributionClientFactory.createDistributionClient(); + EventCallback callback = new EventCallback(client, config); + + IDistributionClientResult initResult = client.init(config, callback); + + if (initResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + String errorMsg = + "Failed to initialize distribution client: " + initResult.getDistributionMessageResult(); + logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); + + // Kick off a timer to retry the SDC connection + Timer timer = new Timer(); + TimerTask task = new SdcConnectionJob(client, config, callback, timer); + timer.schedule(task, new Date(), 60000); + } else { + // Start distribution client + logger.debug(ModelLoaderMsgs.INITIALIZING, "Starting distribution client..."); + IDistributionClientResult startResult = client.start(); + if (startResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + String errorMsg = + "Failed to start distribution client: " + startResult.getDistributionMessageResult(); + logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); + + // Kick off a timer to retry the SDC connection + Timer timer = new Timer(); + TimerTask task = new SdcConnectionJob(client, config, callback, timer); + timer.schedule(task, new Date(), 60000); + } else { + logger.info(ModelLoaderMsgs.INITIALIZING, "Connection to SDC established"); + } + } + } + } + + /** + * Shut down the process. + */ + private void shutdown() { + preShutdownOperations(); + + // TODO: Find a better way to shut down the model loader. + try { + // Give logs time to write to file + Thread.sleep(2000); + } catch (InterruptedException e) { // NOSONAR + // Nothing we can do at this point + logger.debug(e.getMessage()); + } + + Runtime.getRuntime().halt(1); + } + + /** + * (non-Javadoc) + * + * @see org.onap.aai.modelloader.service.ModelLoaderInterface#loadModel(java.lang.String) + */ + @Override + public Response loadModel(String modelid) { + return Response.ok("{\"model_loaded\":\"" + modelid + "\"}").build(); + } + + /** + * (non-Javadoc) + * + * @see org.onap.aai.modelloader.service.ModelLoaderInterface#saveModel(java.lang.String, java.lang.String) + */ + @Override + public Response saveModel(String modelid, String modelname) { + return Response.ok("{\"model_saved\":\"" + modelid + "-" + modelname + "\"}").build(); + } + + @Override + public Response ingestModel(String modelName, String modelVersion, String payload) throws IOException { + boolean success; + + if (config.getIngestSimulatorEnabled()) { + try { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Received test artifact"); + + List<Artifact> catalogArtifacts = new ArrayList<>(); + List<Artifact> modelArtifacts = new ArrayList<>(); + + IArtifactInfo artifactInfo = new ArtifactInfoImpl(); + ((ArtifactInfoImpl) artifactInfo).setArtifactName(modelName); + ((ArtifactInfoImpl) artifactInfo).setArtifactVersion(modelVersion); + + byte[] csarFile = Base64.getDecoder().decode(payload); + + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Generating xml models from test artifact"); + + new ArtifactDownloadManager(client, config).processToscaArtifacts(modelArtifacts, catalogArtifacts, + csarFile, artifactInfo, "test-transaction-id", modelVersion); + + List<IArtifactInfo> artifacts = new ArrayList<>(); + artifacts.add(artifactInfo); + INotificationData notificationData = new NotificationDataImpl(); + ((NotificationDataImpl) notificationData).setDistributionID("TestDistributionID"); + + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Loading xml models from test artifact"); + + success = new ArtifactDeploymentManager(client, config).deploy(notificationData, artifacts, + modelArtifacts, catalogArtifacts); + + } catch (Exception e) { + return Response.serverError().entity(e).build(); + } + } else { + logger.debug("Simulation interface disabled"); + success = false; + } + + Response response; + if (success) { + response = Response.ok().build(); + } else { + response = Response.serverError().build(); + } + + return response; + } } diff --git a/src/main/java/org/onap/aai/modelloader/service/NotificationDataImpl.java b/src/main/java/org/onap/aai/modelloader/service/NotificationDataImpl.java new file mode 100644 index 0000000..28611ff --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/service/NotificationDataImpl.java @@ -0,0 +1,117 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * 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 java.util.Collections; +import java.util.List; +import org.openecomp.sdc.api.notification.IArtifactInfo; +import org.openecomp.sdc.api.notification.INotificationData; +import org.openecomp.sdc.api.notification.IResourceInstance; + +public class NotificationDataImpl implements INotificationData { + + private String distributionID; + + @Override + public IArtifactInfo getArtifactMetadataByUUID(String arg0) { + return null; + } + + @Override + public String getDistributionID() { + return distributionID; + } + + public void setDistributionID(String distributionID) { + this.distributionID = distributionID; + } + + @Override + public List<IResourceInstance> getResources() { + return Collections.emptyList(); + } + + @Override + public List<IArtifactInfo> getServiceArtifacts() { + return Collections.emptyList(); + } + + @Override + public String getServiceDescription() { + return null; + } + + @Override + public String getServiceInvariantUUID() { + return null; + } + + @Override + public String getServiceName() { + return null; + } + + @Override + public String getServiceUUID() { + return null; + } + + @Override + public String getServiceVersion() { + return null; + } + + @Override + public String getWorkloadContext() { + return null; + } + + @Override + public void setWorkloadContext(String arg0) { + // Unsupported method - not expected to be called + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((distributionID == null) ? 0 : distributionID.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NotificationDataImpl other = (NotificationDataImpl) obj; + if (distributionID == null) { + if (other.distributionID != null) + return false; + } else if (!distributionID.equals(other.distributionID)) + return false; + return true; + } + +} diff --git a/src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java b/src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java index 19a6f4e..d30e6dd 100644 --- a/src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java +++ b/src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java @@ -20,58 +20,54 @@ */ package org.onap.aai.modelloader.service; -import java.util.Date; import java.util.Timer; import java.util.TimerTask; - -import org.onap.aai.modelloader.config.ModelLoaderConfig; -import org.onap.aai.modelloader.notification.EventCallback; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.modelloader.config.ModelLoaderConfig; +import org.onap.aai.modelloader.notification.EventCallback; import org.openecomp.sdc.api.IDistributionClient; import org.openecomp.sdc.api.results.IDistributionClientResult; import org.openecomp.sdc.utils.DistributionActionResultEnum; public class SdcConnectionJob extends TimerTask { - static Logger logger = LoggerFactory.getInstance().getLogger(SdcConnectionJob.class.getName()); + static Logger logger = LoggerFactory.getInstance().getLogger(SdcConnectionJob.class.getName()); - private IDistributionClient client; - private ModelLoaderConfig config; - private EventCallback callback; - private Timer timer; + private IDistributionClient client; + private ModelLoaderConfig config; + private EventCallback callback; + private Timer timer; - public SdcConnectionJob(IDistributionClient client, - ModelLoaderConfig config, - EventCallback callback, - Timer timer) { - this.client = client; - this.timer = timer; - this.callback = callback; - this.config = config; - } + public SdcConnectionJob(IDistributionClient client, ModelLoaderConfig config, EventCallback callback, Timer timer) { + this.client = client; + this.timer = timer; + this.callback = callback; + this.config = config; + } - @Override - public void run() { + @Override + public void run() { + if (!config.getASDCConnectionDisabled()) { - IDistributionClientResult initResult = client.init(config, callback); + IDistributionClientResult initResult = client.init(config, callback); - if (initResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - String errorMsg = "Failed to initialize distribution client: " - + initResult.getDistributionMessageResult(); - logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); - return; - } + if (initResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + String errorMsg = + "Failed to initialize distribution client: " + initResult.getDistributionMessageResult(); + logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); + return; + } - IDistributionClientResult startResult = client.start(); - if (startResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { - String errorMsg = "Failed to start distribution client: " - + startResult.getDistributionMessageResult(); - logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); - return; - } + IDistributionClientResult startResult = client.start(); + if (startResult.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) { + String errorMsg = "Failed to start distribution client: " + startResult.getDistributionMessageResult(); + logger.error(ModelLoaderMsgs.ASDC_CONNECTION_ERROR, errorMsg); + return; + } - // Success. Cancel the timer job - timer.cancel(); - logger.info(ModelLoaderMsgs.INITIALIZING, "Connection to SDC established"); - } + // Success. Cancel the timer job + timer.cancel(); + logger.info(ModelLoaderMsgs.INITIALIZING, "Connection to SDC established"); + } + } } 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 29a4409..a5a7bc5 100644 --- a/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java +++ b/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java @@ -27,53 +27,48 @@ import org.json.XML; public class JsonXmlConverter {
- /**
- * Determines whether or not the supplied text string represents a valid
- * JSON structure or not.
- *
- * @param text - The text to be evaluated.
- *
- * @return - true if the string represents a valid JSON object,
- * false, otherwise.
- */
- public static boolean isValidJson(String text) {
- try {
- new JSONObject(text);
- } catch (JSONException ex) {
- try {
- new JSONArray(text);
- } catch (JSONException ex1) {
- return false;
- }
+ private JsonXmlConverter() {
+ throw new AssertionError("Instantiating utility class.");
}
- return true;
- }
+ /**
+ * Determines whether or not the supplied text string represents a valid JSON structure or not.
+ *
+ * @param text The text to be evaluated.
+ * @return - true if the string represents a valid JSON object, false, otherwise.
+ */
+ public static boolean isValidJson(String text) {
+ try {
+ new JSONObject(text);
+ } catch (JSONException ex) {
+ try {
+ new JSONArray(text);
+ } catch (JSONException ex1) {
+ return false;
+ }
+ }
- /**
- * Takes a text string representing a valid JSON structure and converts it to
- * an equivalent XML string.
- *
- * @param jsonText - The JSON string to convert to XML.
- *
- * @return - An XML string representation of the supplied JSON string.
- */
- public static String convertJsonToXml(String jsonText) {
- JSONObject jsonObj = new JSONObject(jsonText);
- String xmlText = XML.toString(jsonObj);
- return xmlText;
- }
+ return true;
+ }
+
+ /**
+ * Takes a text string representing a valid JSON structure and converts it to an equivalent XML string.
+ *
+ * @param jsonText The JSON string to convert to XML.
+ * @return an XML string representation of the supplied JSON string.
+ */
+ public static String convertJsonToXml(String jsonText) {
+ return XML.toString(new JSONObject(jsonText));
+ }
- /**
- * Takes a text string representing a valid XML structure and converts it to
- * an equivalent JSON string.
- *
- * @param xmlText - The XML string to convert to JSON.
- *
- * @return - A JSON string representation of the supplied XML string.
- */
- public static String convertXmlToJson(String xmlText) {
- JSONObject jsonObj = XML.toJSONObject(xmlText);
- return jsonObj.toString();
- }
+ /**
+ * Takes a text string representing a valid XML structure and converts it to an equivalent JSON string.
+ *
+ * @param xmlText The XML string to convert to JSON.
+ * @return a JSON string representation of the supplied XML string.
+ */
+ public static String convertXmlToJson(String xmlText) {
+ JSONObject jsonObj = XML.toJSONObject(xmlText);
+ return jsonObj.toString();
+ }
}
|