diff options
Diffstat (limited to 'adapters/mso-sdnc-adapter/src/main')
23 files changed, 1768 insertions, 34 deletions
diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterPortType.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterPortType.java index 254fea0ba3..f4c8234407 100644 --- a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterPortType.java +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterPortType.java @@ -36,15 +36,15 @@ import javax.xml.bind.annotation.XmlSeeAlso; * */ //BPEL SDNCAdapter SOAP WebService - impl class in impl pkg -@WebService(targetNamespace = "http://domain2.att.com/workflow/sdnc/adapter/wsdl/v1", name = "SDNCAdapterPortType") +@WebService(targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/wsdl/v1", name = "SDNCAdapterPortType") @XmlSeeAlso({ObjectFactory.class}) @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) public interface SDNCAdapterPortType { - @WebResult(name = "SDNCAdapterResponse", targetNamespace = "http://domain2.att.com/workflow/sdnc/adapter/schema/v1", partName = "SDNCAdapterResponse") + @WebResult(name = "SDNCAdapterResponse", targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/schema/v1", partName = "SDNCAdapterResponse") @WebMethod(operationName = "SDNCAdapter") public SDNCAdapterResponse sdncAdapter( - @WebParam(partName = "SDNCAdapterRequest", name = "SDNCAdapterRequest", targetNamespace = "http://domain2.att.com/workflow/sdnc/adapter/schema/v1") + @WebParam(partName = "SDNCAdapterRequest", name = "SDNCAdapterRequest", targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/schema/v1") SDNCAdapterRequest sdncAdapterRequest ); diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterRequest.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterRequest.java index 6b75949453..5da1e51d43 100644 --- a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterRequest.java +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterRequest.java @@ -41,7 +41,7 @@ import org.openecomp.mso.adapters.sdnc.impl.Utils; * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> - * <element ref="{http://domain2.att.com/workflow/sdnc/adapter/schema/v1}RequestHeader"/> + * <element ref="{http://org.openecomp/workflow/sdnc/adapter/schema/v1}RequestHeader"/> * <element name="RequestData" type="{http://www.w3.org/2001/XMLSchema}anyType"/> * </sequence> * </restriction> diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterService.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterService.java index 0b63ad6dea..1e33789ba8 100644 --- a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterService.java +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/SDNCAdapterService.java @@ -42,15 +42,15 @@ import org.openecomp.mso.logger.MessageEnum; //BPEL SDNCAdapter SOAP WebService @WebServiceClient(name = "SDNCAdapterService", wsdlLocation = "main/resources/SDNCAdapter.wsdl", - targetNamespace = "http://domain2.att.com/workflow/sdnc/adapter/wsdl/v1") + targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/wsdl/v1") public class SDNCAdapterService extends Service { private static MsoLogger logger = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA); public final static URL WSDL_LOCATION; - public final static QName SERVICE = new QName("http://domain2.att.com/workflow/sdnc/adapter/wsdl/v1", "SDNCAdapterService"); - public final static QName SDNCAdapterSoapHttpPort = new QName("http://domain2.att.com/workflow/sdnc/adapter/wsdl/v1", "SDNCAdapterSoapHttpPort"); + public final static QName SERVICE = new QName("http://org.openecomp/workflow/sdnc/adapter/wsdl/v1", "SDNCAdapterService"); + public final static QName SDNCAdapterSoapHttpPort = new QName("http://org.openecomp/workflow/sdnc/adapter/wsdl/v1", "SDNCAdapterSoapHttpPort"); static { URL wsdlUrl = null; try { diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCAdapterCallbackRequest.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCAdapterCallbackRequest.java index fd16e4754c..f62c984ef9 100644 --- a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCAdapterCallbackRequest.java +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCAdapterCallbackRequest.java @@ -42,7 +42,7 @@ import org.openecomp.mso.logger.MessageEnum; * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> - * <element ref="{http://domain2.att.com/workflow/sdnc/adapter/schema/v1}CallbackHeader"/> + * <element ref="{http://org.openecomp/workflow/sdnc/adapter/schema/v1}CallbackHeader"/> * <element name="RequestData" type="{http://www.w3.org/2001/XMLSchema}anyType"/> * </sequence> * </restriction> diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCCallbackAdapterPortType.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCCallbackAdapterPortType.java index 6818e67e75..d792b9ca18 100644 --- a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCCallbackAdapterPortType.java +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCCallbackAdapterPortType.java @@ -37,15 +37,15 @@ import org.openecomp.mso.adapters.sdnc.SDNCAdapterResponse; * */ //SDNCAdapter to BPEL Async response WEB Service -@WebService(targetNamespace = "http://domain2.att.com/workflow/sdnc/adapter/callback/wsdl/v1", name = "SDNCCallbackAdapterPortType") +@WebService(targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/callback/wsdl/v1", name = "SDNCCallbackAdapterPortType") @XmlSeeAlso({ObjectFactory.class}) @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) public interface SDNCCallbackAdapterPortType { - @WebResult(name = "SDNCAdapterResponse", targetNamespace = "http://domain2.att.com/workflow/sdnc/adapter/schema/v1", partName = "SDNCAdapterCallbackResponse") + @WebResult(name = "SDNCAdapterResponse", targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/schema/v1", partName = "SDNCAdapterCallbackResponse") @WebMethod(operationName = "SDNCAdapterCallback") public SDNCAdapterResponse sdncAdapterCallback( - @WebParam(partName = "SDNCAdapterCallbackRequest", name = "SDNCAdapterCallbackRequest", targetNamespace = "http://domain2.att.com/workflow/sdnc/adapter/schema/v1") + @WebParam(partName = "SDNCAdapterCallbackRequest", name = "SDNCAdapterCallbackRequest", targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/schema/v1") SDNCAdapterCallbackRequest sdncAdapterCallbackRequest ); } diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCCallbackAdapterService.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCCallbackAdapterService.java index 6fa8e035a5..bbac6a30cb 100644 --- a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCCallbackAdapterService.java +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/SDNCCallbackAdapterService.java @@ -40,14 +40,14 @@ import org.openecomp.mso.logger.MsoLogger; //SDNCAdapter to BPEL Async response WEB Service @WebServiceClient(name = "SDNCCallbackAdapterService", wsdlLocation = "main/resources/SDNCCallbackAdapter.wsdl", - targetNamespace = "http://domain2.att.com/workflow/sdnc/adapter/callback/wsdl/v1") + targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/callback/wsdl/v1") public class SDNCCallbackAdapterService extends Service { private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA); public final static URL WSDL_LOCATION; - public final static QName SERVICE = new QName("http://domain2.att.com/workflow/sdnc/adapter/callback/wsdl/v1", "SDNCCallbackAdapterService"); - public final static QName SDNCCallbackAdapterSoapHttpPort = new QName("http://domain2.att.com/workflow/sdnc/adapter/callback/wsdl/v1", "SDNCCallbackAdapterSoapHttpPort"); + public final static QName SERVICE = new QName("http://org.openecomp/workflow/sdnc/adapter/callback/wsdl/v1", "SDNCCallbackAdapterService"); + public final static QName SDNCCallbackAdapterSoapHttpPort = new QName("http://org.openecomp/workflow/sdnc/adapter/callback/wsdl/v1", "SDNCCallbackAdapterSoapHttpPort"); static { URL wsdlUrl = null; try { diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/package-info.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/package-info.java index 0d6f900f47..35334dfa74 100644 --- a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/package-info.java +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/client/package-info.java @@ -18,6 +18,6 @@ * ============LICENSE_END========================================================= */ -@javax.xml.bind.annotation.XmlSchema(namespace = "http://domain2.att.com/workflow/sdnc/adapter/schema/v1", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) +@javax.xml.bind.annotation.XmlSchema(namespace = "http://org.openecomp/workflow/sdnc/adapter/schema/v1", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package org.openecomp.mso.adapters.sdnc.client; diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/impl/Constants.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/impl/Constants.java index 6cc0ecbd92..78983291c6 100644 --- a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/impl/Constants.java +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/impl/Constants.java @@ -7,9 +7,9 @@ * 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. @@ -23,11 +23,12 @@ package org.openecomp.mso.adapters.sdnc.impl; public interface Constants { + public static final String BPEL_REST_URL_PROP = "org.openecomp.mso.adapters.sdnc.rest.bpelurl"; public static final String BPEL_URL_PROP = "org.openecomp.mso.adapters.sdnc.bpelurl"; - public static final String DEFAULT_BPEL_URL = "http://msobpel.mtcnj.aic.cip.att.com:8080//active-bpel/services/SDNCAdapterCallbackV1"; + public static final String DEFAULT_BPEL_URL = "http://localhost:8080//active-bpel/services/SDNCAdapterCallbackV1"; public static final String MY_URL_PROP = "org.openecomp.mso.adapters.sdnc.myurl"; - public static final String DEFAULT_MY_URL = "https://msojra.mtcnj.aic.cip.att.com:8443/adapters/rest/SDNCNotify"; + public static final String DEFAULT_MY_URL = "https://localhost:8443/adapters/rest/SDNCNotify"; public static final String SDNC_AUTH_PROP = "org.openecomp.mso.adapters.sdnc.sdncauth"; public static final String DEFAULT_SDNC_AUTH = "406B2AE613211B6FB52466DE6E1769AC"; diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/impl/SDNCAdapterPortTypeImpl.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/impl/SDNCAdapterPortTypeImpl.java index 887c0a9990..0eeacaf5fc 100644 --- a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/impl/SDNCAdapterPortTypeImpl.java +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/impl/SDNCAdapterPortTypeImpl.java @@ -35,7 +35,7 @@ import org.openecomp.mso.properties.MsoPropertiesException; import org.openecomp.mso.properties.MsoPropertiesFactory; //BPEL SDNCAdapter SOAP Web Service implementation -@WebService(serviceName = "SDNCAdapterService", endpointInterface = "org.openecomp.mso.adapters.sdnc.SDNCAdapterPortType", targetNamespace = "http://domain2.att.com/workflow/sdnc/adapter/wsdl/v1") +@WebService(serviceName = "SDNCAdapterService", endpointInterface = "org.openecomp.mso.adapters.sdnc.SDNCAdapterPortType", targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/wsdl/v1") public class SDNCAdapterPortTypeImpl implements SDNCAdapterPortType { private MsoPropertiesFactory msoPropertiesFactory=new MsoPropertiesFactory(); diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/package-info.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/package-info.java index 58359c69b0..55819c6e4d 100644 --- a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/package-info.java +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/package-info.java @@ -18,6 +18,6 @@ * ============LICENSE_END========================================================= */ -@javax.xml.bind.annotation.XmlSchema(namespace = "http://domain2.att.com/workflow/sdnc/adapter/schema/v1", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) +@javax.xml.bind.annotation.XmlSchema(namespace = "http://org.openecomp/workflow/sdnc/adapter/schema/v1", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package org.openecomp.mso.adapters.sdnc; diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/BPRestCallback.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/BPRestCallback.java new file mode 100644 index 0000000000..52b1f19b5f --- /dev/null +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/BPRestCallback.java @@ -0,0 +1,173 @@ +/*- + * ============LICENSE_START======================================================= + * OPENECOMP - MSO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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========================================================= + */ +package org.openecomp.mso.adapters.sdnc.sdncrest; + +import org.openecomp.mso.adapters.sdnc.impl.Constants; +import org.openecomp.mso.logger.MessageEnum; +import org.openecomp.mso.logger.MsoAlarmLogger; +import org.openecomp.mso.logger.MsoLogger; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; + +import javax.xml.bind.DatatypeConverter; + +/** + * Sends asynchronous messages to the BPMN workflow message service. + */ +public class BPRestCallback { + private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA); + private static final MsoAlarmLogger ALARMLOGGER = new MsoAlarmLogger(); + + /** + * Sends a message to the BPMN workflow message service. The URL path is + * constructed using the specified message type and correlator. + * @param workflowMessageUrl the base BPMN WorkflowMessage URL + * @param messageType the message type + * @param correlator the message correlator + * @param message the JSON content + * @return true if the message was consumed successfully by the endpoint + */ + public boolean send(String workflowMessageUrl, String messageType, String correlator, String message) { + LOGGER.debug(getClass().getSimpleName() + ".send(" + + "workflowMessageUrl=" + workflowMessageUrl + + " messageType=" + messageType + + " correlator=" + correlator + + " message=" + message + + ")"); + + while (workflowMessageUrl.endsWith("/")) { + workflowMessageUrl = workflowMessageUrl.substring(0, workflowMessageUrl.length()-1); + } + + String endpoint = workflowMessageUrl + "/" + SDNCAdapterUtils.encodeURLPathSegment(messageType) + + "/" + SDNCAdapterUtils.encodeURLPathSegment(correlator); + + return send(endpoint, message); + } + + /** + * Sends a message to the BPMN workflow message service. The specified URL + * must have the message type and correlator already embedded in it. + * @param url the endpoint URL + * @param message the JSON content + * @return true if the message was consumed successfully by the endpoint + */ + public boolean send(String url, String message) { + LOGGER.debug(getClass().getSimpleName() + ".send(" + + "url=" + url + + " message=" + message + + ")"); + + LOGGER.info(MessageEnum.RA_CALLBACK_BPEL, message == null ? "[no content]" : message, "Camunda", ""); + + HttpPost method = null; + HttpResponse httpResponse = null; + + try { + // TODO: configurable timeout? + int timeout = 60 * 1000; + + RequestConfig requestConfig = RequestConfig.custom() + .setSocketTimeout(timeout) + .setConnectTimeout(timeout) + .setConnectionRequestTimeout(timeout) + .build(); + + HttpClient client = HttpClientBuilder.create().build(); + method = new HttpPost(url); + method.setConfig(requestConfig); + + if (message != null) { + method.setEntity(new StringEntity(message, ContentType.APPLICATION_JSON)); + } + + boolean error = false; + + try { + // AAF Integration, disabled for now due to the constrains from other party + // String userCredentials = CredentialConstants.getDecryptedCredential(Constants.DEFAULT_BPEL_AUTH); + // Once AAF enabled, the credential shall be get by triggering the CredentialConstants.getDecryptedCredential -- remove line + String userCredentials = SDNCAdapterProperties.getEncryptedProperty(Constants.BPEL_AUTH_PROP, + Constants.DEFAULT_BPEL_AUTH, Constants.ENCRYPTION_KEY); + String authorization = "Basic " + DatatypeConverter.printBase64Binary(userCredentials.getBytes()); + method.setHeader("Authorization", authorization); + } catch (Exception e) { + LOGGER.error(MessageEnum.RA_SET_CALLBACK_AUTH_EXC, "Camunda", "", MsoLogger.ErrorCode.BusinessProcesssError, + "Unable to set authorization in callback request", e); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, + "Unable to set authorization in callback request: " + e.getMessage()); + error = true; + } + + if (!error) { + httpResponse = client.execute(method); + + @SuppressWarnings("unused") + String responseContent = null; + + if (httpResponse.getEntity() != null) { + responseContent = EntityUtils.toString(httpResponse.getEntity(), "UTF-8"); + } + + if (httpResponse.getStatusLine().getStatusCode() >= 300) { + String msg = "Received error response to callback request: " + httpResponse.getStatusLine(); + LOGGER.error(MessageEnum.RA_CALLBACK_BPEL_EXC, "Camunda", "", MsoLogger.ErrorCode.BusinessProcesssError, msg); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, msg); + } + + httpResponse = null; + } + + method.reset(); + method = null; + return true; + } catch (Exception e) { + LOGGER.error(MessageEnum.RA_CALLBACK_BPEL_EXC, "Camunda", "", MsoLogger.ErrorCode.BusinessProcesssError, + "Error sending callback request", e); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, + "Error sending callback request: " + e.getMessage()); + return false; + } finally { + if (httpResponse != null) { + try { + EntityUtils.consume(httpResponse.getEntity()); + } catch (Exception e) { + // Ignore + } + } + + if (method != null) { + try { + method.reset(); + } catch (Exception e) { + // Ignore + } + } + + LOGGER.info(MessageEnum.RA_CALLBACK_BPEL_COMPLETE, "Camunda", ""); + } + } +}
\ No newline at end of file diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCAdapterProperties.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCAdapterProperties.java new file mode 100644 index 0000000000..ba8fdfb936 --- /dev/null +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCAdapterProperties.java @@ -0,0 +1,85 @@ +/*- + * ============LICENSE_START======================================================= + * OPENECOMP - MSO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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========================================================= + */ +package org.openecomp.mso.adapters.sdnc.sdncrest; + +import org.openecomp.mso.logger.MessageEnum; +import org.openecomp.mso.logger.MsoLogger; +import org.openecomp.mso.properties.MsoJavaProperties; +import org.openecomp.mso.properties.MsoPropertiesException; +import org.openecomp.mso.properties.MsoPropertiesFactory; + +/** + * Static methods to access SDNC adapter properties. + */ +public final class SDNCAdapterProperties { + private static final String MSO_PROPERTIES_ID = "MSO_PROP_SDNC_ADAPTER"; + private static final MsoPropertiesFactory MSO_PROPERTIES_FACTORY = new MsoPropertiesFactory(); + private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA); + + /** + * Gets the value of an SDNC adapter property. + * @param key the property key + * @param defaultValue the default value to use if the property does not + * exist or if an error occurs + */ + public static String getProperty(String key, String defaultValue) { + MsoJavaProperties properties; + + try { + properties = MSO_PROPERTIES_FACTORY.getMsoJavaProperties(MSO_PROPERTIES_ID); + } catch (MsoPropertiesException e) { + LOGGER.error (MessageEnum.NO_PROPERTIES, "Unknown. Mso Properties ID not found in cache: " + MSO_PROPERTIES_ID, + "SDNC", "", MsoLogger.ErrorCode.DataError, "Exception - Mso Properties ID not found in cache", e); + return defaultValue; + } + + String value = properties.getProperty(key, defaultValue); + LOGGER.debug("Config read for " + MSO_PROPERTIES_ID + " - key:" + key + " value:" + value); + return value; + } + + /** + * Gets the value of an SDNC adapter property. + * @param key the property key + * @param defaultValue the default value to use if the property does not + * exist or if an error occurs + */ + public static String getEncryptedProperty(String key, String defaultValue, String encryptionKey) { + MsoJavaProperties properties; + + try { + properties = MSO_PROPERTIES_FACTORY.getMsoJavaProperties(MSO_PROPERTIES_ID); + } catch (MsoPropertiesException e) { + LOGGER.error (MessageEnum.NO_PROPERTIES, "Unknown. Mso Properties ID not found in cache: " + MSO_PROPERTIES_ID, + "SDNC", "", MsoLogger.ErrorCode.DataError, "Exception - Mso Properties ID not found in cache", e); + return defaultValue; + } + + String value = properties.getEncryptedProperty(key, defaultValue, encryptionKey); + LOGGER.debug("Config read for " + MSO_PROPERTIES_ID + " - key:" + key); + return value; + } + + /** + * Instantiation is not allowed. + */ + private SDNCAdapterProperties() { + } +}
\ No newline at end of file diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCAdapterRest.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCAdapterRest.java new file mode 100644 index 0000000000..c4ed50a1b1 --- /dev/null +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCAdapterRest.java @@ -0,0 +1,239 @@ +/*- + * ============LICENSE_START======================================================= + * OPENECOMP - MSO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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========================================================= + */ +package org.openecomp.mso.adapters.sdnc.sdncrest; + +import org.openecomp.mso.HealthCheckUtils; +import org.openecomp.mso.adapters.sdnc.impl.Constants; +import org.openecomp.mso.adapters.sdncrest.SDNCEvent; +import org.openecomp.mso.adapters.sdncrest.SDNCResponseCommon; +import org.openecomp.mso.adapters.sdncrest.SDNCServiceError; +import org.openecomp.mso.adapters.sdncrest.SDNCServiceRequest; +import org.openecomp.mso.logger.MessageEnum; +import org.openecomp.mso.logger.MsoAlarmLogger; +import org.openecomp.mso.logger.MsoLogger; +import org.openecomp.mso.utils.UUIDChecker; +import org.apache.http.HttpStatus; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.*; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.text.ParseException; + +/** + * SDNC REST adapter interface added in 1702 to support the SDNC "agnostic" API. + */ +@Path("/") +public class SDNCAdapterRest { + private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA); + private static final MsoAlarmLogger ALARMLOGGER = new MsoAlarmLogger(); + + private static final String MSO_PROPERTIES_ID = "MSO_PROP_SDNC_ADAPTER"; + + @HEAD + @GET + @Path("/v1/sdnc/healthcheck") + @Produces(MediaType.TEXT_HTML) + public Response healthcheck(@QueryParam("requestId") String requestId) { + long startTime = System.currentTimeMillis(); + MsoLogger.setServiceName("Healthcheck"); + UUIDChecker.verifyOldUUID(requestId, LOGGER); + HealthCheckUtils healthCheck = new HealthCheckUtils(); + + if (!healthCheck.siteStatusCheck(LOGGER, startTime)) { + return HealthCheckUtils.HEALTH_CHECK_NOK_RESPONSE; + } + + if (!healthCheck.configFileCheck(LOGGER, startTime, MSO_PROPERTIES_ID)) { + return HealthCheckUtils.NOT_STARTED_RESPONSE; + } + + LOGGER.debug("healthcheck - Successful"); + return HealthCheckUtils.HEALTH_CHECK_RESPONSE; + } + + /** + * Processes an SDNCServiceRequest (a request for "agnostic" API services) from BP. + * @param request the request + * @param msoRequestId the request ID for the top-level MSO flow (used for logging only) + * @param msoServiceInstanceId the top-level service-instance-id (used for logging only) + */ + @POST + @Path("/v1/sdnc/services") + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public Response service( + SDNCServiceRequest request, + @HeaderParam(value="att-mso-request-id") String msoRequestId, + @HeaderParam(value="att-mso-service-instance-id") String msoServiceInstanceId) { + + MsoLogger.setLogContext(msoRequestId, msoServiceInstanceId); + + try { + LOGGER.debug(getClass().getSimpleName() + ".service(request)" + + " entered with request: " + request.toJson()); + + SDNCServiceRequestTask task = new SDNCServiceRequestTask(request, msoRequestId, + msoServiceInstanceId, "/services"); + + try { + Thread thread = new Thread(task); + thread.start(); + } catch (Exception e) { + String msg = "Failed to start thread to run SDNCServiceTask"; + LOGGER.error(MessageEnum.RA_SEND_REQUEST_SDNC_ERR, "SDNC", "", MsoLogger.ErrorCode.BusinessProcesssError, msg, e); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, msg); + SDNCServiceError error = new SDNCServiceError(request.getSDNCRequestId(), + String.valueOf(HttpStatus.SC_INTERNAL_SERVER_ERROR), e.toString(), "Y"); + LOGGER.debug(getClass().getSimpleName() + ".service(request)" + + " exited with error: " + msg); + return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR) + .entity(new GenericEntity<SDNCServiceError>(error){}) + .build(); + } + + // Send sync response to caller + LOGGER.debug(getClass().getSimpleName() + ".service(request)" + + " exited successfully"); + return Response.status(HttpStatus.SC_ACCEPTED).build(); + } catch (Exception e) { + String msg = "Caught " + e.getClass().getSimpleName() + " in 'service' method"; + LOGGER.error(MessageEnum.RA_SEND_REQUEST_SDNC_ERR, "SDNC", "", MsoLogger.ErrorCode.BusinessProcesssError, msg, e); + LOGGER.debug(getClass().getSimpleName() + ".service(request)" + + " exited with error: " + msg); + SDNCServiceError error = new SDNCServiceError(request.getSDNCRequestId(), + String.valueOf(HttpStatus.SC_INTERNAL_SERVER_ERROR), e.toString(), "Y"); + return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR) + .entity(new GenericEntity<SDNCServiceError>(error){}) + .build(); + } + } + + /** + * Processes a notification from SDNC for "agnostic" API services. + * Note that the "myurl" configuration property specifies the path + * up to and including /SDNCNotify. The /services part of the path + * is added by this class. + * @param content the notification content + */ + @POST + @Path("/SDNCNotify/services") + @Consumes({MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_XML}) + public Response serviceNotification(String content) { + LOGGER.info(MessageEnum.RA_RECEIVE_SDNC_NOTIF, content, "SDNC", "SDNCNotify/services"); + + long startTime = System.currentTimeMillis(); + + try { + // Because the format of a notification is exactly the same as that of + // a synchronous response, we can use the same code to parse it. + SDNCResponseCommon response = SDNCServiceRequestConnector.parseResponseContent(content); + + String bpUrl = SDNCAdapterProperties.getProperty(Constants.BPEL_REST_URL_PROP, null); + + if (bpUrl == null) { + String error = "Missing configuration for: " + Constants.BPEL_REST_URL_PROP; + LOGGER.error(MessageEnum.RA_SDNC_MISS_CONFIG_PARAM, Constants.BPEL_REST_URL_PROP, "SDNC", "", + MsoLogger.ErrorCode.DataError, "Missing config param"); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, error); + return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity(error).build(); + } + + long bpStartTime = System.currentTimeMillis(); + BPRestCallback callback = new BPRestCallback(); + boolean callbackSuccess = callback.send(bpUrl, "SDNCAResponse", response.getSDNCRequestId(), response.toJson()); + + if (callbackSuccess) { + LOGGER.recordMetricEvent(bpStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, + "Sent notification", "BPMN", bpUrl, null); + LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successful"); + } else { + LOGGER.recordMetricEvent(bpStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, + "Failed to send notification", "BPMN", bpUrl, null); + LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, + "Failed to send notification"); + } + + return Response.ok().build(); + } catch (ParseException e) { + LOGGER.error(MessageEnum.RA_PARSING_REQUEST_ERROR, "SDNC", "SDNCNotify/services", + MsoLogger.ErrorCode.SchemaError, e.getMessage()); + LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.SchemaError, e.getMessage()); + return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity(e.getMessage()).build(); + } + } + + /** + * Processes an event notification from SDNC. + * Note that the "myurl" configuration property specifies the path + * up to and including /SDNCNotify. The /activate part of the path + * is added by this class. + * @param content the notification content + */ + @POST + @Path("/SDNCNotify/event") + @Consumes({MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_XML}) + public Response eventNotification(String content) { + LOGGER.info(MessageEnum.RA_RECEIVE_SDNC_NOTIF, content, "SDNC", "SDNCNotify/event"); + + long startTime = System.currentTimeMillis(); + + try { + SDNCEvent event = SDNCEventParser.parse(content); + + String bpUrl = SDNCAdapterProperties.getProperty(Constants.BPEL_REST_URL_PROP, null); + + if (bpUrl == null) { + String error = "Missing configuration for: " + Constants.BPEL_REST_URL_PROP; + LOGGER.error(MessageEnum.RA_SDNC_MISS_CONFIG_PARAM, Constants.BPEL_REST_URL_PROP, "SDNC", "", + MsoLogger.ErrorCode.DataError, "Missing config param"); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, error); + return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity(error).build(); + } + + long bpStartTime = System.currentTimeMillis(); + BPRestCallback callback = new BPRestCallback(); + boolean callbackSuccess = callback.send(bpUrl, "SDNCAEvent", event.getEventCorrelator(), event.toJson()); + + if (callbackSuccess) { + LOGGER.recordMetricEvent(bpStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, + "Sent notification", "BPMN", bpUrl, null); + LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successful"); + } else { + LOGGER.recordMetricEvent(bpStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, + "Failed to send notification", "BPMN", bpUrl, null); + LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, + "Failed to send notification"); + } + + return Response.ok().build(); + } catch (ParseException e) { + LOGGER.error(MessageEnum.RA_PARSING_REQUEST_ERROR, "SDNC", "SDNCNotify/event", + MsoLogger.ErrorCode.SchemaError, e.getMessage()); + LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, + MsoLogger.ResponseCode.SchemaError, e.getMessage()); + return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity(e.getMessage()).build(); + } + } +}
\ No newline at end of file diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCAdapterUtils.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCAdapterUtils.java new file mode 100644 index 0000000000..d97f340a7c --- /dev/null +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCAdapterUtils.java @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * OPENECOMP - MSO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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========================================================= + */ +package org.openecomp.mso.adapters.sdnc.sdncrest; + +import org.springframework.web.util.UriUtils; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +/** + * Utility methods used by SDNCAdapterRest. + */ +public final class SDNCAdapterUtils { + /** + * Returns a node's child elements in a list. + */ + public static List<Element> childElements(Node node) { + List<Element> elements = new ArrayList<Element>(); + + NodeList nodeList = node.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node child = nodeList.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + elements.add((Element) child); + } + } + + return elements; + } + + /** + * Encodes a URL path segment according to RFC 3986 Section 2. + * @param pathSegment the path segment to encode + * @return the encoded path segment + */ + public static String encodeURLPathSegment(String pathSegment) { + try { + return UriUtils.encodePathSegment(pathSegment, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UTF-8 encoding is not supported"); + } + } + + /** + * Instantiation is not allowed. + */ + private SDNCAdapterUtils() { + } +}
\ No newline at end of file diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCConnector.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCConnector.java new file mode 100644 index 0000000000..26c186599c --- /dev/null +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCConnector.java @@ -0,0 +1,309 @@ +/*- + * ============LICENSE_START======================================================= + * OPENECOMP - MSO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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========================================================= + */ +package org.openecomp.mso.adapters.sdnc.sdncrest; + +import org.openecomp.mso.adapters.sdnc.impl.Constants; +import org.openecomp.mso.adapters.sdncrest.SDNCErrorCommon; +import org.openecomp.mso.adapters.sdncrest.SDNCResponseCommon; +import org.openecomp.mso.logger.MessageEnum; +import org.openecomp.mso.logger.MsoAlarmLogger; +import org.openecomp.mso.logger.MsoLogger; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.*; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import javax.xml.XMLConstants; +import javax.xml.bind.DatatypeConverter; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.StringReader; +import java.net.HttpURLConnection; +import java.net.SocketTimeoutException; + +/** + * Sends requests to SDNC and processes the responses. + */ +public abstract class SDNCConnector { + private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA); + private static final MsoAlarmLogger ALARMLOGGER = new MsoAlarmLogger(); + + public SDNCResponseCommon send(String content, TypedRequestTunables rt) { + LOGGER.info(MessageEnum.RA_SEND_REQUEST_SDNC, rt.toString(), "SDNC", ""); + LOGGER.debug("SDNC Request Body:\n" + content); + + HttpRequestBase method = null; + HttpResponse httpResponse = null; + + try { + int timeout = Integer.parseInt(rt.getTimeout()); + + RequestConfig requestConfig = RequestConfig.custom() + .setSocketTimeout(timeout) + .setConnectTimeout(timeout) + .setConnectionRequestTimeout(timeout) + .build(); + + HttpClient client = HttpClientBuilder.create().build(); + + if ("POST".equals(rt.getReqMethod())) { + HttpPost httpPost = new HttpPost(rt.getSdncUrl()); + httpPost.setConfig(requestConfig); + httpPost.setEntity(new StringEntity(content, ContentType.APPLICATION_XML)); + method = httpPost; + } else if ("PUT".equals(rt.getReqMethod())) { + HttpPut httpPut = new HttpPut(rt.getSdncUrl()); + httpPut.setConfig(requestConfig); + httpPut.setEntity(new StringEntity(content, ContentType.APPLICATION_XML)); + method = httpPut; + } else if ("GET".equals(rt.getReqMethod())) { + HttpGet httpGet = new HttpGet(rt.getSdncUrl()); + httpGet.setConfig(requestConfig); + method = httpGet; + } else if ("DELETE".equals(rt.getReqMethod())) { + HttpDelete httpDelete = new HttpDelete(rt.getSdncUrl()); + httpDelete.setConfig(requestConfig); + method = httpDelete; + } + + // AAF Integration, disabled for now due to the constrains from other party + // String userCredentials = CredentialConstants.getSecurityProperties().getEncryptedProperty(CredentialConstants.DEFAULT_AUTH, "", CredentialConstants.getEncryptionKey()); + // if (userCredentials == null) { + // userCredentials = ""; + //} + String userCredentials = SDNCAdapterProperties.getEncryptedProperty(Constants.SDNC_AUTH_PROP, + Constants.DEFAULT_SDNC_AUTH, Constants.ENCRYPTION_KEY); + String authorization = "Basic " + DatatypeConverter.printBase64Binary(userCredentials.getBytes()); + method.setHeader("Authorization", authorization); + + method.setHeader("Accept", "application/yang.data+xml"); + + httpResponse = client.execute(method); + + String responseContent = null; + if (httpResponse.getEntity() != null) { + responseContent = EntityUtils.toString(httpResponse.getEntity(), "UTF-8"); + } + + int statusCode = httpResponse.getStatusLine().getStatusCode(); + String statusMessage = httpResponse.getStatusLine().getReasonPhrase(); + + LOGGER.debug("SDNC Response: " + statusCode + " " + statusMessage + + (responseContent == null ? "" : System.lineSeparator() + responseContent)); + + if (httpResponse.getStatusLine().getStatusCode() >= 300) { + String errMsg = "SDNC returned " + statusCode + " " + statusMessage; + + String errors = analyzeErrors(responseContent); + if (errors != null) { + errMsg += " " + errors; + } + + logError(errMsg); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, errMsg); + return createErrorResponse(statusCode, errMsg, rt); + } + + httpResponse = null; + + method.reset(); + method = null; + + LOGGER.info(MessageEnum.RA_RESPONSE_FROM_SDNC, responseContent, "SDNC", ""); + return createResponseFromContent(statusCode, statusMessage, responseContent, rt); + + } catch (SocketTimeoutException e) { + String errMsg = "Request to SDNC timed out"; + logError(errMsg, e); + return createErrorResponse(HttpURLConnection.HTTP_CLIENT_TIMEOUT, errMsg, rt); + + } catch (ConnectTimeoutException e) { + String errMsg = "Request to SDNC timed out"; + logError(errMsg, e); + return createErrorResponse(HttpURLConnection.HTTP_CLIENT_TIMEOUT, errMsg, rt); + + } catch (Exception e) { + String errMsg = "Error processing request to SDNC"; + logError(errMsg, e); + return createErrorResponse(HttpURLConnection.HTTP_INTERNAL_ERROR, errMsg, rt); + + } finally { + if (httpResponse != null) { + try { + EntityUtils.consume(httpResponse.getEntity()); + } catch (Exception e) { + // Ignore + } + } + + if (method != null) { + try { + method.reset(); + } catch (Exception e) { + // Ignore + } + } + } + } + + protected void logError(String errMsg) { + LOGGER.error(MessageEnum.RA_EXCEPTION_COMMUNICATE_SDNC, "SDNC", "", + MsoLogger.ErrorCode.AvailabilityError, errMsg); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, errMsg); + } + + protected void logError(String errMsg, Throwable t) { + LOGGER.error(MessageEnum.RA_EXCEPTION_COMMUNICATE_SDNC, "SDNC", "", + MsoLogger.ErrorCode.AvailabilityError, errMsg, t); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, errMsg); + } + + /** + * Generates a response object from content received from SDNC. The response + * object may be a success response object or an error response object. This + * method must be overridden by the subclass to return the correct object type. + * @param statusCode the response status code from SDNC (e.g. 200) + * @param statusMessage the response status message from SDNC (e.g. "OK") + * @param responseContent the body of the response from SDNC (possibly null) + * @param rt request tunables + * @return a response object + */ + protected abstract SDNCResponseCommon createResponseFromContent(int statusCode, + String statusMessage, String responseContent, TypedRequestTunables rt); + + /** + * Generates an error response object. This method must be overridden by the + * subclass to return the correct object type. + * @param statusCode the response status code (from SDNC, or internally generated) + * @param errMsg the error message (normally a verbose explanation of the error) + * @param rt request tunables + * @return an error response object + */ + protected abstract SDNCErrorCommon createErrorResponse(int statusCode, + String errMsg, TypedRequestTunables rt); + + /** + * Called by the send() method to analyze errors that may be encoded in the + * content of non-2XX responses. By default, this method tries to parse the + * content as a restconf error. + * <pre> + * xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf" + * </pre> + * If an error (or errors) can be obtained from the content, then the result + * is a string in this format: + * <pre> + * [error-type:TYPE, error-tag:TAG, error-message:MESSAGE] ... + * </pre> + * If no error could be obtained from the content, then the result is null. + * <p> + * The subclass can override this method to provide another implementation. + */ + protected String analyzeErrors(String content) { + if (content == null || content.isEmpty()) { + return null; + } + + // Confirmed with Andrew Shen on 11/1/16 that SDNC will send content like + // this in error responses (non-2XX response codes) to "agnostic" service + // requests. + // + // <errors xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf"> + // <error> + // <error-type>protocol</error-type> + // <error-tag>malformed-message</error-tag> + // <error-message>Error parsing input: The element type "input" must be terminated by the matching end-tag "</input>".</error-message> + // </error> + // </errors> + + String output = null; + + try { + XPathFactory xpathFactory = XPathFactory.newInstance(); + XPath xpath = xpathFactory.newXPath(); + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + InputSource source = new InputSource(new StringReader(content)); + Document doc = documentBuilderFactory.newDocumentBuilder().parse(source); + NodeList errors = (NodeList) xpath.evaluate("errors/error", doc, XPathConstants.NODESET); + + for (int i = 0; i < errors.getLength(); i++) + { + Element error = (Element) errors.item(i); + + String info = ""; + + try { + String errorType = xpath.evaluate("error-type", error); + info += "error-type:" + errorType; + } catch (XPathExpressionException e) { + LOGGER.error(MessageEnum.RA_EVALUATE_XPATH_ERROR, "error-type", error.toString(), "SDNC", "", + MsoLogger.ErrorCode.DataError, "XPath Exception", e); + } + + try { + String errorTag = xpath.evaluate( "error-tag", error); + if (!info.isEmpty()) { + info += ", "; + } + info += "error-tag:" + errorTag; + } catch (XPathExpressionException e) { + LOGGER.error(MessageEnum.RA_EVALUATE_XPATH_ERROR, "error-tag", error.toString(), "SDNC", "", + MsoLogger.ErrorCode.DataError, "XPath Exception", e); + } + + try { + String errorMessage = xpath.evaluate("error-message", error); + if (!info.isEmpty()) { + info += ", "; + } + info += "error-message:" + errorMessage; + } catch (Exception e) { + LOGGER.error(MessageEnum.RA_EVALUATE_XPATH_ERROR, "error-message", error.toString(), "SDNC", "", + MsoLogger.ErrorCode.DataError, "XPath Exception", e); + } + + if (!info.isEmpty()) { + if (output == null) { + output = "[" + info + "]"; + } else { + output += " [" + info + "]"; + } + } + } + } catch (Exception e) { + LOGGER.error (MessageEnum.RA_ANALYZE_ERROR_EXC, "SDNC", "", + MsoLogger.ErrorCode.DataError, "Exception while analyzing errors", e); + } + + return output; + } +} diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCEventParser.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCEventParser.java new file mode 100644 index 0000000000..9808f48e7e --- /dev/null +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCEventParser.java @@ -0,0 +1,156 @@ +/*- + * ============LICENSE_START======================================================= + * OPENECOMP - MSO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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========================================================= + */ +package org.openecomp.mso.adapters.sdnc.sdncrest; + +import org.openecomp.mso.adapters.sdncrest.SDNCEvent; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.StringReader; +import java.text.ParseException; + +/** + * SDNCConnector for "agnostic" API services. + */ +public class SDNCEventParser { + /** + * Parses SDNC event XML. If the content can be parsed and contains all required + * elements, then an object is returned. Otherwise, a ParseException is thrown. + * This method performs no logging or alarming. + * @throws ParseException on error + */ + public static SDNCEvent parse(String content) throws ParseException { + try { + // Note: this document builder is not namespace-aware, so namespaces are ignored. + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + InputSource source = new InputSource(new StringReader(content)); + Document doc = documentBuilderFactory.newDocumentBuilder().parse(source); + + // Find the configuration-event child under the root element. + // The root element is expected to be an "output" element, but we don't really care. + + Element root = doc.getDocumentElement(); + Element configurationEvent = null; + + for (Element child : SDNCAdapterUtils.childElements(root)) { + if ("configuration-event".equals(child.getNodeName())) { + configurationEvent = child; + break; + } + } + + if (configurationEvent == null) { + throw new ParseException("No configuration-event element in SDNC event", 0); + } + + // Process the children of configuration-event + + String eventType = null; + String eventCorrelatorType = null; + String eventCorrelator = null; + Element eventParameters = null; + + for (Element child : SDNCAdapterUtils.childElements(configurationEvent)) { + if ("event-type".equals(child.getNodeName())) { + eventType = child.getTextContent(); + } else if ("event-correlator-type".equals(child.getNodeName())) { + eventCorrelatorType = child.getTextContent(); + } else if ("event-correlator".equals(child.getNodeName())) { + eventCorrelator = child.getTextContent(); + } else if ("event-parameters".equals(child.getNodeName())) { + eventParameters = (Element) child; + } + } + + // event-type is mandatory. + + if (eventType == null || eventType.isEmpty()) { + throw new ParseException("No event-type in SDNC event", 0); + } + + // event-correlator-type is mandatory. + + if (eventCorrelatorType == null || eventCorrelatorType.isEmpty()) { + throw new ParseException("No event-correlator-type in SDNC event", 0); + } + + // event-correlator is mandatory. + + if (eventCorrelator == null || eventCorrelator.isEmpty()) { + throw new ParseException("No event-correlator in SDNC event", 0); + } + + // Create an event object. + + SDNCEvent event = new SDNCEvent(eventType, eventCorrelatorType, eventCorrelator); + + // event-parameters is an optional container element. If present, + // process its children, adding values to the event object. + + if (eventParameters != null) { + for (Element element : SDNCAdapterUtils.childElements(eventParameters)) { + if (!"event-parameter".equals(element.getNodeName())) { + continue; + } + + String tagName = null; + String tagValue = null; + + for (Element child : SDNCAdapterUtils.childElements(element)) { + if ("tag-name".equals(child.getNodeName())) { + tagName = child.getTextContent(); + } else if ("tag-value".equals(child.getNodeName())) { + tagValue = child.getTextContent(); + } + } + + // tag-name is mandatory + + if (tagName == null) { + throw new ParseException("Missing tag-name in SDNC event parameter", 0); + } + + // tag-value is optional. If absent, make it an empty string so we don't + // end up with null values in the parameter map. + + if (tagValue == null) { + tagValue = ""; + } + + event.addParam(tagName, tagValue); + } + } + + return event; + } catch (ParseException e) { + throw e; + } catch (Exception e) { + throw new ParseException("Failed to parse SDNC event", 0); + } + } + + // Instantiation is not allowed. + private SDNCEventParser() { + } +}
\ No newline at end of file diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCServiceRequestConnector.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCServiceRequestConnector.java new file mode 100644 index 0000000000..bd864d085a --- /dev/null +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCServiceRequestConnector.java @@ -0,0 +1,194 @@ +/*- + * ============LICENSE_START======================================================= + * OPENECOMP - MSO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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========================================================= + */ +package org.openecomp.mso.adapters.sdnc.sdncrest; + +import org.openecomp.mso.adapters.sdncrest.SDNCErrorCommon; +import org.openecomp.mso.adapters.sdncrest.SDNCResponseCommon; +import org.openecomp.mso.adapters.sdncrest.SDNCServiceError; +import org.openecomp.mso.adapters.sdncrest.SDNCServiceResponse; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.StringReader; +import java.net.HttpURLConnection; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; + +/** + * SDNCConnector for "agnostic" API services. + */ +public class SDNCServiceRequestConnector extends SDNCConnector { + + @Override + protected SDNCResponseCommon createResponseFromContent(int statusCode, String statusMessage, + String responseContent, TypedRequestTunables rt) { + try { + return parseResponseContent(responseContent); + } catch (ParseException e) { + logError(e.getMessage()); + return createErrorResponse(HttpURLConnection.HTTP_INTERNAL_ERROR, e.getMessage(), rt); + } + } + + @Override + protected SDNCErrorCommon createErrorResponse(int statusCode, String errMsg, + TypedRequestTunables rt) { + return new SDNCServiceError(rt.getReqId(), String.valueOf(statusCode), errMsg, "Y"); + } + + /** + * Parses SDNC synchronous service response content or service notification content. + * If the content can be parsed and contains all required elements, then an object + * is returned. The type of the returned object depends on the response code + * contained in the content. For 2XX response codes, an SDNCServiceResponse is + * returned. Otherwise, an SDNCServiceError is returned. If the content cannot + * be parsed, or if the content does not contain all required elements, a parse + * exception is thrown. This method performs no logging or alarming. + * @throws ParseException on error + */ + public static SDNCResponseCommon parseResponseContent(String responseContent) + throws ParseException { + try { + // Note: this document builder is not namespace-aware, so namespaces are ignored. + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + InputSource source = new InputSource(new StringReader(responseContent)); + Document doc = documentBuilderFactory.newDocumentBuilder().parse(source); + + // Find the configuration-response-common child under the root element. + // The root element is expected to be an "output" element, but we don't really care. + + Element root = doc.getDocumentElement(); + Element configurationResponseCommon = null; + + for (Element child : SDNCAdapterUtils.childElements(root)) { + if ("configuration-response-common".equals(child.getNodeName())) { + configurationResponseCommon = child; + break; + } + } + + if (configurationResponseCommon == null) { + throw new ParseException("No configuration-response-common element in SDNC response", 0); + } + + // Process the children of configuration-response-common. + + String responseCode = null; + String responseMessage = null; + String svcRequestId = null; + String ackFinalIndicator = null; + List<Element> responseParameters = new ArrayList<Element>(); + + for (Element child : SDNCAdapterUtils.childElements(configurationResponseCommon)) { + if ("response-code".equals(child.getNodeName())) { + responseCode = child.getTextContent(); + } else if ("response-message".equals(child.getNodeName())) { + responseMessage = child.getTextContent(); + } else if ("svc-request-id".equals(child.getNodeName())) { + svcRequestId = child.getTextContent(); + } else if ("ack-final-indicator".equals(child.getNodeName())) { + ackFinalIndicator = child.getTextContent(); + } else if ("response-parameters".equals(child.getNodeName())) { + responseParameters.add((Element) child); + } + } + + // svc-request-id is mandatory. + + if (svcRequestId == null || svcRequestId.isEmpty()) { + throw new ParseException("No svc-request-id in SDNC response", 0); + } + + // response-code is mandatory. + + if (responseCode == null || responseCode.isEmpty()) { + throw new ParseException("No response-code in SDNC response", 0); + } + + // ack-final-indicator is optional: default to "Y". + + if (ackFinalIndicator == null) { + ackFinalIndicator = "Y"; + } + + if (!ackFinalIndicator.equals("Y") && !ackFinalIndicator.equals("N")) { + throw new ParseException("Invalid ack-final-indicator in SDNC response: '" + ackFinalIndicator + "'", 0); + } + + // response-message is optional. If the value is empty, omit it from the response object. + + if (responseMessage != null && responseMessage.isEmpty()) { + responseMessage = null; + } + + // If the response code in the message from SDNC was not 2XX, return SDNCServiceError. + + if (!responseCode.matches("2[0-9][0-9]")) { + // Not a 2XX response. Return SDNCServiceError. + return new SDNCServiceError(svcRequestId, responseCode, responseMessage, ackFinalIndicator); + } + + // Create a success response object. + + SDNCServiceResponse response = new SDNCServiceResponse(svcRequestId, + responseCode, responseMessage, ackFinalIndicator); + + // Process any response-parameters that might be present. + + for (Element element : responseParameters) { + String tagName = null; + String tagValue = null; + + for (Element child : SDNCAdapterUtils.childElements(element)) { + if ("tag-name".equals(child.getNodeName())) { + tagName = child.getTextContent(); + } else if ("tag-value".equals(child.getNodeName())) { + tagValue = child.getTextContent(); + } + } + + // tag-name is mandatory + + if (tagName == null) { + throw new ParseException("Missing tag-name in SDNC response parameter", 0); + } + + // tag-value is optional. If absent, make it an empty string so we don't + // end up with null values in the parameter map. + + if (tagValue == null) { + tagValue = ""; + } + + response.addParam(tagName, tagValue); + } + return response; + } catch (ParseException e) { + throw e; + } catch (Exception e) { + throw new ParseException("Failed to parse SDNC response", 0); + } + } +} diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCServiceRequestTask.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCServiceRequestTask.java new file mode 100644 index 0000000000..e52a426b4d --- /dev/null +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SDNCServiceRequestTask.java @@ -0,0 +1,205 @@ +/*- + * ============LICENSE_START======================================================= + * OPENECOMP - MSO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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========================================================= + */ +package org.openecomp.mso.adapters.sdnc.sdncrest; + +import org.openecomp.mso.adapters.sdncrest.SDNCErrorCommon; +import org.openecomp.mso.adapters.sdncrest.SDNCResponseCommon; +import org.openecomp.mso.adapters.sdncrest.SDNCServiceError; +import org.openecomp.mso.adapters.sdncrest.SDNCServiceRequest; +import org.openecomp.mso.logger.MessageEnum; +import org.openecomp.mso.logger.MsoLogger; +import org.apache.http.HttpStatus; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.StringWriter; + +public class SDNCServiceRequestTask implements Runnable { + private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA); + + private final SDNCServiceRequest request; + private final String msoRequestId; + private final String msoServiceInstanceId; + private final String myUrlSuffix; + + public SDNCServiceRequestTask(SDNCServiceRequest request, + String msoRequestId, String msoServiceInstanceId, + String myUrlSuffix) { + this.request = request; + this.msoRequestId = msoRequestId; + this.msoServiceInstanceId = msoServiceInstanceId; + this.myUrlSuffix = myUrlSuffix; + } + + @Override + public void run() + { + MsoLogger.setLogContext(msoRequestId, msoServiceInstanceId); + MsoLogger.setServiceName(getClass().getSimpleName()); + + LOGGER.debug(getClass().getSimpleName() + ".run()" + + " entered with request: " + request.toJson()); + + String sdncRequestId = request.getSDNCRequestId(); + String sdncService = request.getSDNCService(); + String sdncOperation = request.getSDNCOperation(); + + TypedRequestTunables rt = new TypedRequestTunables(sdncRequestId, myUrlSuffix); + rt.setServiceKey(sdncService, sdncOperation); + + if (!rt.setTunables()) { + // Note that the error was logged and alarmed by setTunables() + SDNCServiceError error = new SDNCServiceError(request.getSDNCRequestId(), + String.valueOf(HttpStatus.SC_INTERNAL_SERVER_ERROR), rt.getError(), "Y"); + BPRestCallback callback = new BPRestCallback(); + callback.send(request.getBPNotificationUrl(), error.toJson()); + return; + } + + String xml = genSdncReq(request, rt); + + long sdncStartTime = System.currentTimeMillis(); + SDNCConnector connector = new SDNCServiceRequestConnector(); + SDNCResponseCommon response = connector.send(xml, rt); + + if (response instanceof SDNCErrorCommon) { + LOGGER.recordMetricEvent(sdncStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, + "Received success response from SDNC", "SDNC", sdncService + "." + sdncOperation, null); + } else { + LOGGER.recordMetricEvent(sdncStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, + "Received error response from SDNC", "SDNC", sdncService + "." + sdncOperation, null); + } + + long bpStartTime = System.currentTimeMillis(); + BPRestCallback callback = new BPRestCallback(); + boolean callbackSuccess = callback.send(request.getBPNotificationUrl(), response.toJson()); + + if (callbackSuccess) { + LOGGER.recordMetricEvent(bpStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, + "Sent notification", "BPMN", request.getBPNotificationUrl(), null); + } else { + LOGGER.recordMetricEvent(bpStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, + "Failed to send notification", "BPMN", request.getBPNotificationUrl(), null); + } + } + + private Element addChild(Element parent, String tag) { + Element child = parent.getOwnerDocument().createElement(tag); + parent.appendChild(child); + return child; + } + + private void addTextChild(Element parent, String tag, String text) { + if (text != null) { + Element child = parent.getOwnerDocument().createElement(tag); + child.setTextContent(text); + parent.appendChild(child); + } + } + + private String genSdncReq(SDNCServiceRequest request, TypedRequestTunables rt) { + Document doc; + + try { + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + + doc = documentBuilder.newDocument(); + Element root = doc.createElementNS(rt.getNamespace(), "input"); + doc.appendChild(root); + + Element hdr = addChild(root, rt.getHeaderName()); + addTextChild(hdr, "svc-request-id", rt.getReqId()); + addTextChild(hdr, "svc-notification-url", rt.getMyUrl()); + + Element requestInformation = addChild(root, "request-information"); + addTextChild(requestInformation, "request-id", request.getRequestInformation().getRequestId()); + addTextChild(requestInformation, "source", request.getRequestInformation().getSource()); + addTextChild(requestInformation, "notification-url", request.getRequestInformation().getNotificationUrl()); + + Element serviceInformation = addChild(root, "service-information"); + addTextChild(serviceInformation, "service-type", request.getServiceInformation().getServiceType()); + addTextChild(serviceInformation, "service-instance-id", request.getServiceInformation().getServiceInstanceId()); + addTextChild(serviceInformation, "subscriber-name", request.getServiceInformation().getSubscriberName()); + addTextChild(serviceInformation, "subscriber-global-id", request.getServiceInformation().getSubscriberGlobalId()); + + Element agnosticServiceInformation = addChild(root, "agnostic-service-information"); + addTextChild(agnosticServiceInformation, "operation", request.getSDNCOperation()); + addTextChild(agnosticServiceInformation, "service", request.getSDNCService()); + + // anydata is mandatory in the SDNC schema, so if the data we got is null, + // set use an empty string instead to ensure we generate an empty element. + + String anydata = request.getSDNCServiceData(); + if (anydata == null) { + anydata = ""; + } + + // content-type is also mandatory. + + String contentType = request.getSDNCServiceDataType(); + + if (contentType == null || contentType.isEmpty()) { + if (anydata.isEmpty()) { + contentType = "XML"; + } else { + if (anydata.startsWith("<")) { + contentType = "XML"; + } else { + contentType = "JSON"; + } + } + } + + addTextChild(agnosticServiceInformation, "content-type", contentType); + addTextChild(agnosticServiceInformation, "anydata", anydata); + } catch (Exception e) { + LOGGER.error(MessageEnum.RA_ERROR_CREATE_SDNC_REQUEST, "SDNC", "", + MsoLogger.ErrorCode.BusinessProcesssError, "Exception in genSdncReq", e); + return null; + } + + String xml; + + try { + StringWriter writer = new StringWriter(); + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + transformer.transform(new DOMSource(doc), new StreamResult(writer)); + xml = writer.toString(); + } catch (Exception e) { + LOGGER.error(MessageEnum.RA_ERROR_CONVERT_XML2STR, "", "", + MsoLogger.ErrorCode.DataError, "Exception - domToStr", e); + return(null); + } + + LOGGER.debug("Formatted SDNC service request XML:\n" + xml); + return xml; + } +} diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SNIROResponse.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SNIROResponse.java new file mode 100644 index 0000000000..2045b8c353 --- /dev/null +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/SNIROResponse.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * OPENECOMP - MSO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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========================================================= + */ +package org.openecomp.mso.adapters.sdnc.sdncrest; + +import org.openecomp.mso.adapters.sdnc.impl.Constants; +import org.openecomp.mso.logger.MessageEnum; +import org.openecomp.mso.logger.MsoAlarmLogger; +import org.openecomp.mso.logger.MsoLogger; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +/** + * A temporary interface to support notifications from SNIRO to BPMN. + * We added this to the SDNC adapter because we didn't have time to + * develop a SNIRO adapter in 1702. + */ +@Path("/") +public class SNIROResponse { + private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA); + private static final MsoAlarmLogger ALARMLOGGER = new MsoAlarmLogger(); + + @POST + @Path("/SDNCNotify/SNIROResponse/{correlator}") + @Consumes("*/*") + @Produces({MediaType.TEXT_PLAIN}) + public Response serviceNotification(@PathParam("correlator") String correlator, String content) { + LOGGER.info(MessageEnum.RA_RECEIVE_SDNC_NOTIF, content, "SDNC", "SDNCNotify/SNIROResponse"); + + long startTime = System.currentTimeMillis(); + + String bpUrl = SDNCAdapterProperties.getProperty(Constants.BPEL_REST_URL_PROP, null); + + if (bpUrl == null) { + String error = "Missing configuration for: " + Constants.BPEL_REST_URL_PROP; + LOGGER.error(MessageEnum.RA_SDNC_MISS_CONFIG_PARAM, Constants.BPEL_REST_URL_PROP, "SDNC", "", + MsoLogger.ErrorCode.DataError, "Missing config param"); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, error); + return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity(error).build(); + } + + long bpStartTime = System.currentTimeMillis(); + BPRestCallback callback = new BPRestCallback(); + boolean callbackSuccess = callback.send(bpUrl, "SNIROResponse", correlator, content); + + if (callbackSuccess) { + LOGGER.recordMetricEvent(bpStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, + "Sent notification", "BPMN", bpUrl, null); + LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successful"); + } else { + LOGGER.recordMetricEvent(bpStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, + "Failed to send notification", "BPMN", bpUrl, null); + LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, + "Failed to send notification"); + } + + return Response.status(204).build(); + } +}
\ No newline at end of file diff --git a/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/TypedRequestTunables.java b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/TypedRequestTunables.java new file mode 100644 index 0000000000..4c270cee60 --- /dev/null +++ b/adapters/mso-sdnc-adapter/src/main/java/org/openecomp/mso/adapters/sdnc/sdncrest/TypedRequestTunables.java @@ -0,0 +1,224 @@ +/*- + * ============LICENSE_START======================================================= + * OPENECOMP - MSO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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========================================================= + */ +package org.openecomp.mso.adapters.sdnc.sdncrest; + +import org.openecomp.mso.adapters.sdnc.impl.Constants; +import org.openecomp.mso.logger.MessageEnum; +import org.openecomp.mso.logger.MsoAlarmLogger; +import org.openecomp.mso.logger.MsoLogger; +import org.openecomp.mso.properties.MsoJavaProperties; +import org.openecomp.mso.properties.MsoPropertiesException; +import org.openecomp.mso.properties.MsoPropertiesFactory; + +/** + * Typed Request Tunables. Each entry is identified by a TYPE in the property name. + * Different types can have different keys. + * <p> + * General format: + * <pre> + * org.openecomp.mso.adapters.sdnc.TYPE.KEY1[.KEY2...]=METHOD|TIMEOUT|URL|HEADER|NAMESPACE + * </pre> + * Currently supported type(s): service + * <pre> + * org.openecomp.mso.adapters.sdnc.service.SERVICE.OPERATION=METHOD|TIMEOUT|URL|HEADER|NAMESPACE + * </pre> + */ +public class TypedRequestTunables { + + private static final String MSO_PROPERTIES_ID = "MSO_PROP_SDNC_ADAPTER"; + + private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA); + private static final MsoAlarmLogger ALARMLOGGER = new MsoAlarmLogger(); + + private final MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory(); + + private final String reqId; + private final String myUrlSuffix; + private String key = null; + private String error = null; + + // tunables (all are required) + private String reqMethod = null; + private String timeout = null; + private String sdncUrl = null; + private String headerName = null; + private String namespace = null; + private String myUrl = null; + + public TypedRequestTunables(String reqId, String myUrlSuffix) { + this.reqId = reqId; + this.myUrlSuffix = myUrlSuffix; + } + + /** + * Sets the key for a service request: + * <pre> + * org.openecomp.mso.adapters.sdnc.service.SERVICE.OPERATION + * </pre> + * @param service the sdncService + * @param operation the sdncOperation + */ + public void setServiceKey(String service, String operation) { + key = Constants.REQUEST_TUNABLES + ".service." + service + "." + operation; + LOGGER.debug("Generated " + getClass().getSimpleName() + " key: " + key); + } + + /** + * Gets the SDNC request ID. + */ + public String getReqId() { + return reqId; + } + + /** + * Gets the generated key. + */ + public String getKey() { + return key; + } + + /** + * Gets the most recent error, or null if there was no error. + */ + public String getError() { + return error; + } + + public String getReqMethod() { + return reqMethod; + } + + public String getTimeout() { + return timeout; + } + + public String getSdncUrl() { + return sdncUrl; + } + + public String getHeaderName() { + return headerName; + } + + public String getNamespace() { + return namespace; + } + + /** + * Gets the SDNC adapter notification URL, trimmed of trailing '/' characters. + */ + public String getMyUrl() { + return myUrl; + } + + /** + * Returns true if successful. If there is an error, it is logged and alarmed. + * The error description may be retrieved by calling getError(). + */ + public boolean setTunables() { + error = null; + MsoJavaProperties properties; + + try { + properties = msoPropertiesFactory.getMsoJavaProperties(MSO_PROPERTIES_ID); + } catch (MsoPropertiesException e) { + error = "Mso Properties ID not found in cache: " + MSO_PROPERTIES_ID; + LOGGER.error(MessageEnum.LOAD_PROPERTIES_FAIL, "Unknown. " + error, "SDNC", "", + MsoLogger.ErrorCode.DataError, "Exception - Mso Properties ID not found in cache", e); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, error); + return false; + } + + String value = properties.getProperty(key, ""); + + if (value.equals("")) { + error = "Missing configuration for: " + key; + LOGGER.error(MessageEnum.RA_SDNC_MISS_CONFIG_PARAM, key, "SDNC", "", MsoLogger.ErrorCode.DataError, "Missing config param"); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, error); + return false; + } + + String[] parts = value.split("\\|"); + + if (parts.length != 5) { + error = "Invalid configuration for: " + key; + LOGGER.error(MessageEnum.RA_SDNC_INVALID_CONFIG, key, value, "SDNC", "", MsoLogger.ErrorCode.DataError, "Invalid config"); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, error); + return false; + } + + reqMethod = parts[0]; + LOGGER.debug("Request Method is set to: " + reqMethod); + + timeout = parts[1]; + LOGGER.debug("Timeout is set to: " + timeout); + + String urlPropKey = Constants.REQUEST_TUNABLES + "." + parts[2]; + sdncUrl = properties.getProperty(urlPropKey, ""); + + if (sdncUrl.equals("")) { + error = "Missing configuration for: " + urlPropKey; + LOGGER.error(MessageEnum.RA_SDNC_MISS_CONFIG_PARAM, urlPropKey, "SDNC", "", MsoLogger.ErrorCode.DataError, "Missing config param"); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, error); + return false; + } + + LOGGER.debug("SDNC Url is set to: " + sdncUrl); + + headerName = parts[3]; + LOGGER.debug("Header Name is set to: " + headerName); + + namespace = parts[4]; + LOGGER.debug("Namespace is set to: " + namespace); + + myUrl = properties.getProperty(Constants.MY_URL_PROP, ""); + + if (myUrl.equals("")) { + error = "Missing configuration for: " + Constants.MY_URL_PROP; + LOGGER.error(MessageEnum.RA_SDNC_MISS_CONFIG_PARAM, Constants.MY_URL_PROP, "SDNC", "", + MsoLogger.ErrorCode.DataError, "Missing config param"); + ALARMLOGGER.sendAlarm("MsoInternalError", MsoAlarmLogger.CRITICAL, error); + return false; + } + + while (myUrl.endsWith("/")) { + myUrl = myUrl.substring(0, myUrl.length()-1); + } + + myUrl += myUrlSuffix; + + LOGGER.debug(toString()); + return true; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + + "reqId=" + reqId + + (key == null ? "" : ", key=" + key) + + (reqMethod == null ? "" : ", reqMethod=" + reqMethod) + + (sdncUrl == null ? "" : ", sdncUrl=" + sdncUrl) + + (timeout == null ? "" : ", timeout=" + timeout) + + (headerName == null ? "" : ", headerName=" + headerName) + + (namespace == null ? "" : ", namespace=" + namespace) + + (myUrl == null ? "" : ", myUrl=" + myUrl) + + "]"; + } +}
\ No newline at end of file diff --git a/adapters/mso-sdnc-adapter/src/main/resources/SDNCAdapter.wsdl b/adapters/mso-sdnc-adapter/src/main/resources/SDNCAdapter.wsdl index 2f4c5ad5eb..7a66cd418b 100644 --- a/adapters/mso-sdnc-adapter/src/main/resources/SDNCAdapter.wsdl +++ b/adapters/mso-sdnc-adapter/src/main/resources/SDNCAdapter.wsdl @@ -1,16 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" - xmlns:sdncadaptersc="http://domain2.att.com/workflow/sdnc/adapter/schema/v1" + xmlns:sdncadaptersc="http://org.openecomp/workflow/sdnc/adapter/schema/v1" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:tns="http://domain2.att.com/workflow/sdnc/adapter/wsdl/v1" + xmlns:tns="http://org.openecomp/workflow/sdnc/adapter/wsdl/v1" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" - targetNamespace="http://domain2.att.com/workflow/sdnc/adapter/wsdl/v1"> + targetNamespace="http://org.openecomp/workflow/sdnc/adapter/wsdl/v1"> <types> <schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" - targetNamespace="http://domain2.att.com/workflow/sdnc/adapter/wsdl/v1"> - <import namespace="http://domain2.att.com/workflow/sdnc/adapter/schema/v1" + targetNamespace="http://org.openecomp/workflow/sdnc/adapter/wsdl/v1"> + <import namespace="http://org.openecomp/workflow/sdnc/adapter/schema/v1" schemaLocation="SDNCAdapterSchema.xsd" /> </schema> </types> diff --git a/adapters/mso-sdnc-adapter/src/main/resources/SDNCAdapterSchema.xsd b/adapters/mso-sdnc-adapter/src/main/resources/SDNCAdapterSchema.xsd index f0e4435771..ed904d4a2e 100644 --- a/adapters/mso-sdnc-adapter/src/main/resources/SDNCAdapterSchema.xsd +++ b/adapters/mso-sdnc-adapter/src/main/resources/SDNCAdapterSchema.xsd @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> -<schema targetNamespace="http://domain2.att.com/workflow/sdnc/adapter/schema/v1" +<schema targetNamespace="http://org.openecomp/workflow/sdnc/adapter/schema/v1" xmlns="http://www.w3.org/2001/XMLSchema" - xmlns:tns="http://domain2.att.com/workflow/sdnc/adapter/schema/v1" - xmlns:sdncadaptersc="http://domain2.att.com/workflow/sdnc/adapter/schema/v1" + xmlns:tns="http://org.openecomp/workflow/sdnc/adapter/schema/v1" + xmlns:sdncadaptersc="http://org.openecomp/workflow/sdnc/adapter/schema/v1" elementFormDefault="qualified"> diff --git a/adapters/mso-sdnc-adapter/src/main/resources/SDNCCallbackAdapter.wsdl b/adapters/mso-sdnc-adapter/src/main/resources/SDNCCallbackAdapter.wsdl index 1429b5f1c7..0a106752fb 100644 --- a/adapters/mso-sdnc-adapter/src/main/resources/SDNCCallbackAdapter.wsdl +++ b/adapters/mso-sdnc-adapter/src/main/resources/SDNCCallbackAdapter.wsdl @@ -1,16 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" - xmlns:sdncadaptersc="http://domain2.att.com/workflow/sdnc/adapter/schema/v1" + xmlns:sdncadaptersc="http://org.openecomp/workflow/sdnc/adapter/schema/v1" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:tns="http://domain2.att.com/workflow/sdnc/adapter/callback/wsdl/v1" + xmlns:tns="http://org.openecomp/workflow/sdnc/adapter/callback/wsdl/v1" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" - targetNamespace="http://domain2.att.com/workflow/sdnc/adapter/callback/wsdl/v1"> + targetNamespace="http://org.openecomp/workflow/sdnc/adapter/callback/wsdl/v1"> <types> <schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" - targetNamespace="http://domain2.att.com/workflow/sdnc/adapter/wsdl/v1"> - <import namespace="http://domain2.att.com/workflow/sdnc/adapter/schema/v1" + targetNamespace="http://org.openecomp/workflow/sdnc/adapter/wsdl/v1"> + <import namespace="http://org.openecomp/workflow/sdnc/adapter/schema/v1" schemaLocation="SDNCAdapterSchema.xsd" /> </schema> </types> |