summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/onap
diff options
context:
space:
mode:
authorArul.Nambi <arul.nambi@amdocs.com>2017-09-13 15:13:29 -0400
committerArul.Nambi <arul.nambi@amdocs.com>2017-09-13 15:13:37 -0400
commit059f42e1a2289ecb2cb5835b8b14a0d098c9e1d3 (patch)
treeeb9218adc67f1183b9d371a4ca10fc31ece3b23c /src/main/java/org/onap
parent7813ad1766bb168f92ce6c0c10a6926a2f00b519 (diff)
Renaming openecomp to onap
Issue-ID: AAI-208 Change-Id: I559ba27fba96364c506730e8cbac05a9e6591694 Signed-off-by: Arul.Nambi <arul.nambi@amdocs.com>
Diffstat (limited to 'src/main/java/org/onap')
-rw-r--r--src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java242
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/Artifact.java47
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/ArtifactHandler.java40
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/ArtifactType.java31
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifact.java34
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifactHandler.java193
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/model/AbstractModelArtifact.java86
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/model/IModelParser.java32
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifact.java211
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactHandler.java86
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactParser.java194
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/model/ModelParserFactory.java88
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/model/ModelSorter.java236
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/model/ModelV8Artifact.java123
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/model/ModelV8ArtifactParser.java136
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifact.java114
-rw-r--r--src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifactParser.java136
-rw-r--r--src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMsg.java78
-rw-r--r--src/main/java/org/onap/aai/modelloader/notification/EventCallback.java293
-rw-r--r--src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java483
-rw-r--r--src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java56
-rw-r--r--src/main/java/org/onap/aai/modelloader/service/ModelLoaderMsgs.java111
-rw-r--r--src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java204
-rw-r--r--src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java80
-rw-r--r--src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java82
25 files changed, 3416 insertions, 0 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
new file mode 100644
index 0000000..cca99f1
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java
@@ -0,0 +1,242 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.config;
+
+import org.eclipse.jetty.util.security.Password;
+import org.openecomp.sdc.api.consumer.IConfiguration;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+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_AAI = PREFIX_MODEL_LOADER_CONFIG + ".aai.";
+ public static final String PREFIX_DEBUG = PREFIX_MODEL_LOADER_CONFIG + ".debug.";
+
+ // Configuration file properties
+ protected static final String PROP_ML_DISTRIBUTION_ACTIVE_SERVER_TLS_AUTH =
+ PREFIX_DISTRIBUTION_CLIENT + "ACTIVE_SERVER_TLS_AUTH";
+ protected static final String PROP_ML_DISTRIBUTION_ASDC_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_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_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_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_DEBUG_INGEST_SIMULATOR = PREFIX_DEBUG + "INGEST_SIMULATOR";
+
+ private Properties modelLoaderProperties = null;
+
+ private String certLocation = ".";
+
+ private List<String> artifactTypes = null;
+
+ /**
+ * This is the class constructor.
+ *
+ * @param modelLoaderProperties properties needed to be configured for the model loader
+ * @param certLocation location of the certificate
+ */
+ public ModelLoaderConfig(Properties modelLoaderProperties, String certLocation) {
+ this.modelLoaderProperties = modelLoaderProperties;
+ this.certLocation = certLocation;
+
+ // Get list of artifacts
+ artifactTypes = new ArrayList<String>();
+ if (modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ARTIFACT_TYPES) != null) {
+ String[] artTypeList = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ARTIFACT_TYPES)
+ .split(",");
+ for (String artType : artTypeList) {
+ artifactTypes.add(artType);
+ }
+ }
+ }
+
+ @Override
+ public boolean activateServerTLSAuth() {
+ String value = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ACTIVE_SERVER_TLS_AUTH);
+ return value == null ? false : Boolean.parseBoolean(value);
+ }
+
+ @Override
+ public String getAsdcAddress() {
+ return modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ASDC_ADDRESS);
+ }
+
+ @Override
+ public String getConsumerGroup() {
+ return modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_CONSUMER_GROUP);
+ }
+
+ @Override
+ public String getConsumerID() {
+ return modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_CONSUMER_ID);
+ }
+
+ @Override
+ public String getEnvironmentName() {
+ return modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_ENVIRONMENT_NAME);
+ }
+
+ @Override
+ public String getKeyStorePassword() {
+ return Password
+ .deobfuscate(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_KEYSTORE_PASSWORD));
+ }
+
+ @Override
+ public String getKeyStorePath() {
+ return certLocation + modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_KEYSTORE_FILE);
+ }
+
+ @Override
+ public String getPassword() {
+ return Password.deobfuscate(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_PASSWORD));
+ }
+
+ @Override
+ public int getPollingInterval() {
+ return Integer
+ .parseInt(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_POLLING_INTERVAL));
+ }
+
+ @Override
+ public int getPollingTimeout() {
+ return Integer
+ .parseInt(modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_POLLING_TIMEOUT));
+ }
+
+ @Override
+ public List<String> getRelevantArtifactTypes() {
+ return artifactTypes;
+ }
+
+ @Override
+ public String getUser() {
+ return modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_USER);
+ }
+
+ @Override
+ public boolean isFilterInEmptyResources() {
+ return false;
+ }
+
+ @Override
+ public Boolean isUseHttpsWithDmaap() {
+ String useHTTPS = modelLoaderProperties.getProperty(PROP_ML_DISTRIBUTION_HTTPS_WITH_DMAAP);
+ return useHTTPS == null ? false : Boolean.valueOf(useHTTPS);
+ }
+
+ public String getAaiKeyStorePath() {
+ return certLocation + "/" + modelLoaderProperties.getProperty(PROP_AAI_KEYSTORE_FILE);
+ }
+
+ public String getAaiKeyStorePassword() {
+ return Password.deobfuscate(modelLoaderProperties.getProperty(PROP_AAI_KEYSTORE_PASSWORD));
+ }
+
+ public String getAaiBaseUrl() {
+ return modelLoaderProperties.getProperty(PROP_AAI_BASE_URL);
+ }
+
+ public String getAaiModelUrl(String version) {
+ return modelLoaderProperties.getProperty(PROP_AAI_MODEL_RESOURCE_URL).replace("v*", version);
+ }
+
+ public String getAaiNamedQueryUrl(String version) {
+ return modelLoaderProperties.getProperty(PROP_AAI_NAMED_QUERY_RESOURCE_URL).replace("v*", version);
+ }
+
+ public String getAaiVnfImageUrl() {
+ return modelLoaderProperties.getProperty(PROP_AAI_VNF_IMAGE_RESOURCE_URL);
+ }
+
+ public String getAaiAuthenticationUser() {
+ return modelLoaderProperties.getProperty(PROP_AAI_AUTHENTICATION_USER);
+ }
+
+ /**
+ * @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));
+
+ if ((password != null) && (password.equals(""))) {
+ return null;
+ }
+
+ return password;
+ }
+
+ /**
+ * @return a boolean value indicating whether the simulator is enabled.
+ */
+ public boolean getIngestSimulatorEnabled() {
+ String propValue = modelLoaderProperties.getProperty(PROP_DEBUG_INGEST_SIMULATOR);
+
+ if (propValue == null) {
+ return false;
+ }
+
+ if (propValue.compareToIgnoreCase("enabled") == 0) {
+ return true;
+ }
+
+ return false;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/modelloader/entity/Artifact.java b/src/main/java/org/onap/aai/modelloader/entity/Artifact.java
new file mode 100644
index 0000000..cf612ce
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/Artifact.java
@@ -0,0 +1,47 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.entity;
+
+public abstract class Artifact {
+
+ private String payload;
+ private ArtifactType type;
+
+ public Artifact(ArtifactType type) {
+ this.type = type;
+ }
+
+ public ArtifactType getType() {
+ return type;
+ }
+
+ 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
new file mode 100644
index 0000000..b52b1a6
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/ArtifactHandler.java
@@ -0,0 +1,40 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.entity;
+
+import java.util.List;
+
+import org.onap.aai.modelloader.config.ModelLoaderConfig;
+
+public abstract class ArtifactHandler {
+
+ protected ModelLoaderConfig config;
+
+ public ArtifactHandler(ModelLoaderConfig config) {
+ this.config = config;
+ }
+
+ public abstract boolean pushArtifacts(List<Artifact> artifacts, String distributionId);
+
+}
diff --git a/src/main/java/org/onap/aai/modelloader/entity/ArtifactType.java b/src/main/java/org/onap/aai/modelloader/entity/ArtifactType.java
new file mode 100644
index 0000000..33b7d61
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/ArtifactType.java
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.entity;
+
+public enum ArtifactType {
+ 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
new file mode 100644
index 0000000..1ca6b25
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifact.java
@@ -0,0 +1,34 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.entity.catalog;
+
+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);
+ }
+}
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
new file mode 100644
index 0000000..9ef3f6f
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/catalog/VnfCatalogArtifactHandler.java
@@ -0,0 +1,193 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+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 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.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+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;
+
+
+public class VnfCatalogArtifactHandler extends ArtifactHandler {
+
+ private static Logger logger = LoggerFactory.getInstance()
+ .getLogger(VnfCatalogArtifactHandler.class.getName());
+
+ public VnfCatalogArtifactHandler(ModelLoaderConfig config) {
+ super(config);
+ }
+
+ @Override
+ public boolean pushArtifacts(List<Artifact> artifacts, String distributionId) {
+ for (Artifact art : artifacts) {
+ VnfCatalogArtifact vnfCatalog = (VnfCatalogArtifact) art;
+ String artifactPayload = vnfCatalog.getPayload();
+
+ 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);
+
+ int numParts = cat.getPartNumberList().size();
+
+ for (int i = 0; i < numParts; i++) {
+
+ PartNumberList pnl = cat.getPartNumberList().get(i);
+
+ String application = pnl.getVendorInfo().getVendorModel();
+ String applicationVendor = pnl.getVendorInfo().getVendorName();
+
+ int numVersions = pnl.getSoftwareVersionList().size();
+
+ for (int j = 0; j < numVersions; j++) {
+ String applicationVersion = pnl.getSoftwareVersionList().get(j).getSoftwareVersion();
+
+ String imageId = "vnf image " + applicationVendor + " " + application + " "
+ + applicationVersion;
+
+ String queryURI = "application-vendor=" + applicationVendor + "&application=" + application + "&application-version=" + applicationVersion;
+
+ String getUrl = config.getAaiBaseUrl() + config.getAaiVnfImageUrl() + "?" + UriUtils.encodePath(queryURI, "UTF-8");
+
+ 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;
+ }
+ 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.");
+ } 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;
+ }
+ }
+ }
+
+ } 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;
+ }
+ }
+
+ 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
+ }
+ }
+
+}
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
new file mode 100644
index 0000000..a942cf6
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/model/AbstractModelArtifact.java
@@ -0,0 +1,86 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.entity.model;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+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;
+
+public abstract class AbstractModelArtifact extends Artifact {
+
+ private String modelNamespace;
+ private String modelNamespaceVersion;
+ private Set<String> referencedModelIds = new HashSet<String>();
+
+ 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 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/IModelParser.java b/src/main/java/org/onap/aai/modelloader/entity/model/IModelParser.java
new file mode 100644
index 0000000..0d34908
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/model/IModelParser.java
@@ -0,0 +1,32 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.entity.model;
+
+import java.util.List;
+
+import org.onap.aai.modelloader.entity.Artifact;
+
+public interface IModelParser {
+ public List<Artifact> parse(byte[] 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
new file mode 100644
index 0000000..f0e848d
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifact.java
@@ -0,0 +1,211 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.entity.model;
+
+import java.io.StringWriter;
+import java.util.List;
+
+import javax.ws.rs.core.Response;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.onap.aai.modelloader.config.ModelLoaderConfig;
+import org.onap.aai.modelloader.entity.ArtifactType;
+import org.onap.aai.modelloader.restclient.AaiRestClient;
+import org.onap.aai.modelloader.service.ModelLoaderMsgs;
+import org.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+import org.w3c.dom.Node;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+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;
+
+ 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;
+ }
+ 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;
+ }
+ }
+ 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);
+ }
+
+ // 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 + "/";
+ }
+
+ if ( baseURL.endsWith("/") && subURL.startsWith("/") ) {
+ baseURL = baseURL.substring(0, baseURL.length()-1);
+ }
+
+ if (!subURL.endsWith("/")) {
+ subURL = subURL + "/";
+ }
+
+ String url = baseURL + subURL + instance;
+ return url;
+ }
+
+ private String getModelVerUrl(ModelLoaderConfig config) {
+ String baseURL = config.getAaiBaseUrl().trim();
+ String subURL = null;
+ String instance = null;
+
+ subURL = config.getAaiModelUrl(getModelNamespaceVersion()).trim() + getModelInvariantId() + AAI_MODEL_VER_SUB_URL;
+ 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 + "/";
+ }
+
+ 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();
+ }
+}
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
new file mode 100644
index 0000000..b7da5a2
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactHandler.java
@@ -0,0 +1,86 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.entity.model;
+
+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.service.ModelLoaderMsgs;
+import org.openecomp.cl.api.Logger;
+import org.openecomp.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);
+ }
+
+ @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;
+ }
+
+ // 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<AbstractModelArtifact>();
+ 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);
+ }
+
+ return false;
+ }
+ }
+
+ 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");
+ }
+}
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
new file mode 100644
index 0000000..a362fce
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelArtifactParser.java
@@ -0,0 +1,194 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.entity.model;
+
+import org.onap.aai.modelloader.entity.Artifact;
+import org.onap.aai.modelloader.service.ModelLoaderMsgs;
+import org.openecomp.cl.api.Logger;
+import org.openecomp.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;
+
+ }
+
+}
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
new file mode 100644
index 0000000..df54811
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelParserFactory.java
@@ -0,0 +1,88 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+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.openecomp.cl.api.Logger;
+import org.openecomp.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
new file mode 100644
index 0000000..825cbcb
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelSorter.java
@@ -0,0 +1,236 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+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 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]
+ */
+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>();
+ }
+
+ public Node addEdge(Node node) {
+ Edge edge = new Edge(this, node);
+ outEdges.add(edge);
+ node.inEdges.add(edge);
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return model.getUniqueIdentifier();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ AbstractModelArtifact otherModel = ((Node) other).model;
+ return this.model.getUniqueIdentifier().equals(otherModel.getUniqueIdentifier());
+ }
+
+ @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 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;
+ }
+
+ 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);
+ }
+
+ 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<String, AbstractModelArtifact>();
+ for (Artifact art : models) {
+ AbstractModelArtifact ma = (AbstractModelArtifact) art;
+ versionIdToModelMap.put(ma.getUniqueIdentifier(), ma);
+ }
+
+ 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);
+ }
+ }
+
+ 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);
+ }
+ }
+
+ // 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
new file mode 100644
index 0000000..892d20f
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelV8Artifact.java
@@ -0,0 +1,123 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+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.openecomp.cl.api.Logger;
+import org.openecomp.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
new file mode 100644
index 0000000..af6160f
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/model/ModelV8ArtifactParser.java
@@ -0,0 +1,136 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.entity.model;
+
+import org.onap.aai.modelloader.entity.Artifact;
+import org.onap.aai.modelloader.service.ModelLoaderMsgs;
+import org.openecomp.cl.api.Logger;
+import org.openecomp.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());
+
+ 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);
+
+ 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 )) ) {
+ if (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
new file mode 100644
index 0000000..ece8d4b
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifact.java
@@ -0,0 +1,114 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+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.ArtifactType;
+import org.onap.aai.modelloader.restclient.AaiRestClient;
+import org.onap.aai.modelloader.service.ModelLoaderMsgs;
+import org.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+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;
+ }
+ }
+ 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) {
+ // 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 + "/";
+ }
+
+ if ( baseURL.endsWith("/") && subURL.startsWith("/") ) {
+ baseURL = baseURL.substring(0, baseURL.length()-1);
+ }
+
+ if (!subURL.endsWith("/")) {
+ subURL = subURL + "/";
+ }
+
+ String url = baseURL + subURL + instance;
+ return url;
+ }
+}
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
new file mode 100644
index 0000000..b035592
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/entity/model/NamedQueryArtifactParser.java
@@ -0,0 +1,136 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.entity.model;
+
+import org.onap.aai.modelloader.entity.Artifact;
+import org.onap.aai.modelloader.service.ModelLoaderMsgs;
+import org.openecomp.cl.api.Logger;
+import org.openecomp.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 NamedQueryArtifactParser implements IModelParser {
+
+ 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 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>();
+
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ InputSource is = new InputSource(new StringReader(payload));
+ Document doc = builder.parse(is);
+
+ NamedQueryArtifact model = parseModel(doc.getDocumentElement(), payload);
+
+ 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());
+ }
+
+ return modelList;
+ }
+
+ private NamedQueryArtifact parseModel(Node modelNode, String payload) {
+ NamedQueryArtifact model = new NamedQueryArtifact();
+ model.setPayload(payload);
+
+ Element e = (Element)modelNode;
+ model.setModelNamespace(e.getAttribute("xmlns"));
+
+ parseNode(modelNode, model);
+
+ if (model.getNamedQueryUuid() == null) {
+ return null;
+ }
+
+ 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();
+ }
+ }
+
+ if ( (key != null) && (key.equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY )) ) {
+ if (value != null) {
+ model.addDependentModelId(value);
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMsg.java b/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMsg.java
new file mode 100644
index 0000000..6c267e6
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/notification/DistributionStatusMsg.java
@@ -0,0 +1,78 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.notification;
+
+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;
+ }
+
+ @Override
+ public long getTimestamp() {
+ long currentTimeMillis = System.currentTimeMillis();
+ return currentTimeMillis;
+ }
+
+ @Override
+ public DistributionStatusEnum getStatus() {
+ return status;
+ }
+
+ @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/EventCallback.java b/src/main/java/org/onap/aai/modelloader/notification/EventCallback.java
new file mode 100644
index 0000000..1d40291
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/notification/EventCallback.java
@@ -0,0 +1,293 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.notification;
+
+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.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+import org.openecomp.cl.mdc.MdcContext;
+import org.openecomp.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 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;
+ }
+
+ 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())));
+ }
+ }
+
+ String statusString = "SUCCESS";
+ if (success) {
+ ModelArtifactHandler modelHandler = new ModelArtifactHandler(config);
+ boolean modelDeploySuccess = modelHandler.pushArtifacts(modelArtifacts,
+ data.getDistributionID());
+
+ VnfCatalogArtifactHandler catalogHandler = new VnfCatalogArtifactHandler(config);
+ boolean catalogDeploySuccess = catalogHandler.pushArtifacts(catalogArtifacts,
+ data.getDistributionID());
+
+ 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";
+ }
+
+ 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());
+ }
+ }
+ }
+
+ 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());
+ }
+
+ 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());
+
+ if (sendStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) {
+ logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,
+ "Failed to publish deploy failure status: " + sendStatus.getDistributionMessageResult());
+ }
+ }
+
+ 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());
+
+ if (sendStatus.getDistributionActionResult() != DistributionActionResultEnum.SUCCESS) {
+ logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR,
+ "Failed to publish deploy success status: " + sendStatus.getDistributionMessageResult());
+ }
+ }
+
+ 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/restclient/AaiRestClient.java b/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java
new file mode 100644
index 0000000..712290e
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java
@@ -0,0 +1,483 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+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.openecomp.cl.api.LogFields;
+import org.openecomp.cl.api.LogLine;
+import org.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+import org.openecomp.cl.mdc.MdcContext;
+import org.openecomp.cl.mdc.MdcOverride;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.StringReader;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import java.text.SimpleDateFormat;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.ws.rs.core.Response;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+public class AaiRestClient {
+ public enum MimeType {
+ XML("application/xml"), JSON("application/json");
+
+ private String httpType;
+
+ MimeType(String httpType) {
+ this.httpType = httpType;
+ }
+
+ String getHttpHeaderType() {
+ return httpType;
+ }
+ }
+
+ private static String HEADER_TRANS_ID = "X-TransactionId";
+ private static String HEADER_FROM_APP_ID = "X-FromAppId";
+ private static String HEADER_AUTHORIZATION = "Authorization";
+ private static String ML_APP_NAME = "ModelLoader";
+ private static String RESOURCE_VERSION_PARAM = "resource-version";
+
+ private static SimpleDateFormat dateFormatter = new SimpleDateFormat(
+ "yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
+
+ private static Logger logger = LoggerFactory.getInstance()
+ .getLogger(AaiRestClient.class.getName());
+ private static Logger metricsLogger = LoggerFactory.getInstance()
+ .getMetricsLogger(AaiRestClient.class.getName());
+
+ private ModelLoaderConfig config = null;
+
+ public AaiRestClient(ModelLoaderConfig config) {
+ this.config = config;
+ }
+
+ /**
+ * Send a PUT request to the A&AI.
+ *
+ * @param url
+ * - the url
+ * @param transId
+ * - transaction ID
+ * @param payload
+ * - the XML or JSON payload for the request
+ * @param mimeType
+ * - the content type (XML or JSON)
+ * @return ClientResponse
+ */
+ public ClientResponse putResource(String url, String payload, String transId, MimeType mimeType) {
+ ClientResponse result = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ long startTimeInMs = 0;
+ MdcOverride override = new MdcOverride();
+
+ try {
+ Client client = setupClient();
+
+ baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ if (logger.isDebugEnabled()) {
+ client.addFilter(new LoggingFilter(ps));
+ }
+
+ // Grab the current time so that we can use it for metrics purposes later.
+ startTimeInMs = System.currentTimeMillis();
+ override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs));
+
+ if (useBasicAuth()) {
+ result = client.resource(url).header(HEADER_TRANS_ID, transId)
+ .header(HEADER_FROM_APP_ID, ML_APP_NAME)
+ .header(HEADER_AUTHORIZATION, getAuthenticationCredentials())
+ .type(mimeType.getHttpHeaderType()).put(ClientResponse.class, payload);
+ } else {
+ result = client.resource(url).header(HEADER_TRANS_ID, transId)
+ .header(HEADER_FROM_APP_ID, ML_APP_NAME).type(mimeType.getHttpHeaderType())
+ .put(ClientResponse.class, payload);
+ }
+ } catch (Exception ex) {
+ logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "PUT", url, ex.getLocalizedMessage());
+ return null;
+ } finally {
+ if (logger.isDebugEnabled()) {
+ logger.debug(baos.toString());
+ }
+ }
+
+ if ((result != null) && ((result.getStatus() == Response.Status.CREATED.getStatusCode())
+ || (result.getStatus() == Response.Status.OK.getStatusCode()))) {
+ logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "PUT", url,
+ Integer.toString(result.getStatus()));
+ metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS,
+ new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus())
+ .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION,
+ result.getResponseStatus().toString()),
+ override, "PUT", url, Integer.toString(result.getStatus()));
+ } else {
+ // If response is not 200 OK, then additionally log the reason
+ String respMsg = result.getEntity(String.class);
+ if (respMsg == null) {
+ respMsg = result.getStatusInfo().getReasonPhrase();
+ }
+ logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL, "PUT", url,
+ Integer.toString(result.getStatus()), respMsg);
+ metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL,
+ new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus())
+ .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION,
+ result.getResponseStatus().toString()),
+ override, "PUT", url, Integer.toString(result.getStatus()), respMsg);
+ }
+
+ return result;
+ }
+
+ /**
+ * Send a DELETE request to the A&AI.
+ *
+ * @param url
+ * - the url
+ * @param resourceVersion
+ * - the resource-version of the model to delete
+ * @param transId
+ * - transaction ID
+ * @return ClientResponse
+ */
+ public ClientResponse deleteResource(String url, String resourceVersion, String transId) {
+ ClientResponse result = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ long startTimeInMs = 0;
+ MdcOverride override = new MdcOverride();
+
+ try {
+ Client client = setupClient();
+
+ baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ if (logger.isDebugEnabled()) {
+ client.addFilter(new LoggingFilter(ps));
+ }
+
+ // Grab the current time so that we can use it for metrics purposes later.
+ startTimeInMs = System.currentTimeMillis();
+ override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs));
+
+ if (useBasicAuth()) {
+ result = client.resource(url).queryParam(RESOURCE_VERSION_PARAM, resourceVersion)
+ .header(HEADER_TRANS_ID, transId).header(HEADER_FROM_APP_ID, ML_APP_NAME)
+ .header(HEADER_AUTHORIZATION, getAuthenticationCredentials())
+ .delete(ClientResponse.class);
+ } else {
+ result = client.resource(url).queryParam(RESOURCE_VERSION_PARAM, resourceVersion)
+ .header(HEADER_TRANS_ID, transId).header(HEADER_FROM_APP_ID, ML_APP_NAME)
+ .delete(ClientResponse.class);
+ }
+ } catch (Exception ex) {
+ logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "DELETE", url, ex.getLocalizedMessage());
+ return null;
+ } finally {
+ if (logger.isDebugEnabled()) {
+ logger.debug(baos.toString());
+ }
+ }
+
+ logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "DELETE", url,
+ Integer.toString(result.getStatus()));
+ metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS,
+ new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus()).setField(
+ LogLine.DefinedFields.RESPONSE_DESCRIPTION, result.getResponseStatus().toString()),
+ override, "DELETE", url, Integer.toString(result.getStatus()));
+
+ return result;
+ }
+
+ /**
+ * Send a GET request to the A&AI for a resource.
+ *
+ * @param url
+ * - the url to use
+ * @param transId
+ * - transaction ID
+ * @return ClientResponse
+ */
+ public ClientResponse getResource(String url, String transId, MimeType mimeType) {
+ ClientResponse result = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ long startTimeInMs = 0;
+ MdcOverride override = new MdcOverride();
+
+ try {
+ Client client = setupClient();
+
+ baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ if (logger.isDebugEnabled()) {
+ client.addFilter(new LoggingFilter(ps));
+ }
+
+ // Grab the current time so that we can use it for metrics purposes later.
+ startTimeInMs = System.currentTimeMillis();
+ override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs));
+
+ if (useBasicAuth()) {
+ result = client.resource(url).header(HEADER_TRANS_ID, transId)
+ .header(HEADER_FROM_APP_ID, ML_APP_NAME).accept(mimeType.getHttpHeaderType())
+ .header(HEADER_AUTHORIZATION, getAuthenticationCredentials()).get(ClientResponse.class);
+ } else {
+ result = client.resource(url).header(HEADER_TRANS_ID, transId)
+ .header(HEADER_FROM_APP_ID, ML_APP_NAME).accept(mimeType.getHttpHeaderType())
+ .get(ClientResponse.class);
+
+ }
+ } catch (Exception ex) {
+ logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "GET", url, ex.getLocalizedMessage());
+ return null;
+ } finally {
+ if (logger.isDebugEnabled()) {
+ logger.debug(baos.toString());
+ }
+ }
+
+ logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "GET", url,
+ Integer.toString(result.getStatus()));
+ metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS,
+ new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus()).setField(
+ LogLine.DefinedFields.RESPONSE_DESCRIPTION, result.getResponseStatus().toString()),
+ override, "GET", url, Integer.toString(result.getStatus()));
+
+ return result;
+ }
+
+ /**
+ * Send a POST request to the A&AI.
+ *
+ * @param url
+ * - the url
+ * @param transId
+ * - transaction ID
+ * @param payload
+ * - the XML or JSON payload for the request
+ * @param mimeType
+ * - the content type (XML or JSON)
+ * @return ClientResponse
+ */
+ public ClientResponse postResource(String url, String payload, String transId, MimeType mimeType) {
+ ClientResponse result = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ long startTimeInMs = 0;
+ MdcOverride override = new MdcOverride();
+
+ try {
+ Client client = setupClient();
+
+ baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ if (logger.isDebugEnabled()) {
+ client.addFilter(new LoggingFilter(ps));
+ }
+
+ // Grab the current time so that we can use it for metrics purposes later.
+ startTimeInMs = System.currentTimeMillis();
+ override.addAttribute(MdcContext.MDC_START_TIME, dateFormatter.format(startTimeInMs));
+
+ if (useBasicAuth()) {
+ result = client.resource(url).header(HEADER_TRANS_ID, transId)
+ .header(HEADER_FROM_APP_ID, ML_APP_NAME)
+ .header(HEADER_AUTHORIZATION, getAuthenticationCredentials())
+ .type(mimeType.getHttpHeaderType()).post(ClientResponse.class, payload);
+ } else {
+ result = client.resource(url).header(HEADER_TRANS_ID, transId)
+ .header(HEADER_FROM_APP_ID, ML_APP_NAME).type(mimeType.getHttpHeaderType())
+ .post(ClientResponse.class, payload);
+ }
+ } catch (Exception ex) {
+ logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "POST", url, ex.getLocalizedMessage());
+ return null;
+ } finally {
+ if (logger.isDebugEnabled()) {
+ logger.debug(baos.toString());
+ }
+ }
+
+ if ((result != null) && ((result.getStatus() == Response.Status.CREATED.getStatusCode())
+ || (result.getStatus() == Response.Status.OK.getStatusCode()))) {
+ logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS, "POST", url,
+ Integer.toString(result.getStatus()));
+ metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_SUCCESS,
+ new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus())
+ .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION,
+ result.getResponseStatus().toString()),
+ override, "POST", url, Integer.toString(result.getStatus()));
+ } else {
+ // If response is not 200 OK, then additionally log the reason
+ String respMsg = result.getEntity(String.class);
+ if (respMsg == null) {
+ respMsg = result.getStatusInfo().getReasonPhrase();
+ }
+ logger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL, "POST", url,
+ Integer.toString(result.getStatus()), respMsg);
+ metricsLogger.info(ModelLoaderMsgs.AAI_REST_REQUEST_UNSUCCESSFUL,
+ new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, result.getStatus())
+ .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION,
+ result.getResponseStatus().toString()),
+ override, "POST", url, Integer.toString(result.getStatus()), respMsg);
+ }
+
+ return result;
+ }
+
+ /**
+ * Does a GET on a resource to retrieve the resource version, and then DELETE
+ * that version.
+ *
+ * @param url
+ * - the url
+ * @param transId
+ * - transaction ID
+ * @return ClientResponse
+ */
+ public ClientResponse getAndDeleteResource(String url, String transId) {
+ // First, GET the model
+ ClientResponse getResponse = getResource(url, transId, MimeType.XML);
+ if ((getResponse == null) || (getResponse.getStatus() != Response.Status.OK.getStatusCode())) {
+ return getResponse;
+ }
+
+ // Delete the model using the resource version in the response
+ String resVersion = null;
+ try {
+ resVersion = getResourceVersion(getResponse);
+ } catch (Exception e) {
+ logger.error(ModelLoaderMsgs.AAI_REST_REQUEST_ERROR, "GET", url, e.getLocalizedMessage());
+ return null;
+ }
+
+ return deleteResource(url, resVersion, transId);
+ }
+
+ private Client setupClient() throws IOException, GeneralSecurityException {
+ ClientConfig clientConfig = new DefaultClientConfig();
+
+ HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
+ @Override
+ public boolean verify(String string, SSLSession ssls) {
+ return true;
+ }
+ });
+
+ // Create a trust manager that does not validate certificate chains
+ TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] certs, String authType) {}
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] certs, String authType) {}
+ } };
+
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ FileInputStream fin = new FileInputStream(config.getAaiKeyStorePath());
+ KeyStore ks = KeyStore.getInstance("PKCS12");
+ char[] pwd = config.getAaiKeyStorePassword().toCharArray();
+ ks.load(fin, pwd);
+ kmf.init(ks, pwd);
+
+ ctx.init(kmf.getKeyManagers(), trustAllCerts, null);
+ clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
+ new HTTPSProperties(new HostnameVerifier() {
+ @Override
+ public boolean verify(String theString, SSLSession sslSession) {
+ return true;
+ }
+ }, ctx));
+
+ Client client = Client.create(clientConfig);
+
+ return client;
+ }
+
+ private String getResourceVersion(ClientResponse response)
+ throws ParserConfigurationException, SAXException, IOException {
+ String respData = response.getEntity(String.class);
+
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ InputSource is = new InputSource(new StringReader(respData));
+ Document doc = builder.parse(is);
+
+ NodeList nodeList = doc.getDocumentElement().getChildNodes();
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node currentNode = nodeList.item(i);
+ if (currentNode.getNodeName().equals(RESOURCE_VERSION_PARAM)) {
+ return currentNode.getTextContent();
+ }
+ }
+
+ return null;
+ }
+
+ private String getAuthenticationCredentials() {
+
+ String usernameAndPassword = config.getAaiAuthenticationUser() + ":"
+ + config.getAaiAuthenticationPassword();
+ return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes());
+ }
+
+ public boolean useBasicAuth() {
+ return (config.getAaiAuthenticationUser() != null)
+ && (config.getAaiAuthenticationPassword() != null);
+ }
+}
diff --git a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java
new file mode 100644
index 0000000..9233796
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderInterface.java
@@ -0,0 +1,56 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+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;
+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);
+
+ @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;
+}
diff --git a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderMsgs.java b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderMsgs.java
new file mode 100644
index 0000000..6362e7f
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderMsgs.java
@@ -0,0 +1,111 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.service;
+
+import com.att.eelf.i18n.EELFResourceManager;
+
+import org.openecomp.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");
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java
new file mode 100644
index 0000000..b5f5981
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/service/ModelLoaderService.java
@@ -0,0 +1,204 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+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.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.Properties;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Response;
+
+/**
+ * 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;
+ }
+}
diff --git a/src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java b/src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java
new file mode 100644
index 0000000..30c8709
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/service/SdcConnectionJob.java
@@ -0,0 +1,80 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+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.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+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());
+
+ 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;
+ }
+
+ @Override
+ public void run() {
+
+ 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;
+ }
+
+ 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");
+ }
+}
diff --git a/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java b/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java
new file mode 100644
index 0000000..e307be6
--- /dev/null
+++ b/src/main/java/org/onap/aai/modelloader/util/JsonXmlConverter.java
@@ -0,0 +1,82 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.modelloader.util;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+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;
+ }
+ }
+
+ 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) {
+ JSONObject jsonObj = new JSONObject(jsonText);
+ String xmlText = XML.toString(jsonObj);
+ return xmlText;
+ }
+
+ /**
+ * 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();
+ }
+}