diff --git a/modules/core/src/main/java/org/apache/synapse/SynapseConstants.java b/modules/core/src/main/java/org/apache/synapse/SynapseConstants.java index edcdbeb1b0..3b68e2af03 100644 --- a/modules/core/src/main/java/org/apache/synapse/SynapseConstants.java +++ b/modules/core/src/main/java/org/apache/synapse/SynapseConstants.java @@ -626,6 +626,103 @@ public enum ENDPOINT_TIMEOUT_TYPE { ENDPOINT_TIMEOUT, GLOBAL_TIMEOUT, HTTP_CONNE public static final String ANALYTICS_METADATA = "ANALYTICS_METADATA"; + // Constants for the HTTP Connection + public static final String ENDPOINT_IDENTIFIER = "_INTERNAL_ENDPOINT_REFERENCE"; + public static final String BASIC_AUTH = "Basic Auth"; + public static final String OAUTH = "OAuth"; + public static final String OAUTH_GRANT_TYPE_AUTHORIZATION_CODE = "Authorization Code"; + public static final String OAUTH_GRANT_TYPE_CLIENT_CREDENTIALS = "Client Credentials"; + public static final String OAUTH_GRANT_TYPE_PASSWORD = "Password"; + + public static final String NAME = "name"; + public static final String BASE_URL = "baseUrl"; + public static final String CONNECTION_TYPE = "connectionType"; + public static final String CERTIFICATE_TYPE = "certificateType"; + public static final String AUTH_TYPE = "authType"; + public static final String OAUTH_AUTHORIZATION_MODE = "oauthAuthorizationMode"; + public static final String OAUTH_GRANT_TYPE = "oauthGrantType"; + public static final String BASIC_CREDENTIALS_USERNAME = "basicCredentialsUsername"; + public static final String BASIC_CREDENTIALS_PASSWORD = "basicCredentialsPassword"; + public static final String OAUTH_PASSWORD_GRANT_USERNAME = "oauthPasswordUsername"; + public static final String OAUTH_PASSWORD_GRANT_PASSWORD = "oauthPasswordPassword"; + public static final String OAUTH_PASSWORD_GRANT_CLIENT_ID = "oauthPasswordClientId"; + public static final String OAUTH_PASSWORD_GRANT_CLIENT_SECRET = "oauthPasswordClientSecret"; + public static final String OAUTH_PASSWORD_GRANT_TOKEN_URL = "oauthPasswordTokenUrl"; + public static final String OAUTH_PASSWORD_GRANT_ADDITIONAL_PROPERTIES = "oauthPasswordAdditionalProperties"; + + public static final String OAUTH_CLIENT_CREDENTIALS_GRANT_CLIENT_ID = "oauthClientClientId"; + public static final String OAUTH_CLIENT_CREDENTIALS_GRANT_CLIENT_SECRET = "oauthClientClientSecret"; + public static final String OAUTH_CLIENT_CREDENTIALS_GRANT_TOKEN_URL = "oauthClientTokenUrl"; + public static final String OAUTH_CLIENT_CREDENTIALS_GRANT_ADDITIONAL_PROPERTIES = "oauthClientAdditionalProperties"; + + public static final String OAUTH_AUTHORIZATION_GRANT_CLIENT_SECRET = "oauthAuthorizationClientSecret"; + public static final String OAUTH_AUTHORIZATION_GRANT_CLIENT_ID = "oauthAuthorizationClientId"; + public static final String OAUTH_AUTHORIZATION_GRANT_TOKEN_URL = "oauthAuthorizationTokenUrl"; + public static final String OAUTH_AUTHORIZATION_GRANT_REFRESH_TOKEN = "oauthAuthorizationRefreshToken"; + public static final String OAUTH_AUTHORIZATION_GRANT_ADDITIONAL_PROPERTIES = "oauthAuthorizationAdditionalProperties"; + + public static final String OAUTH_CLIENT_ID = "oauthClientId"; + public static final String TIMEOUT_DURATION = "timeoutDuration"; + public static final String TIMEOUT_ACTION = "timeoutAction"; + public static final String SUSPEND_ERROR_CODES = "suspendErrorCodes"; + public static final String SUSPEND_INITIAL_DURATION = "suspendInitialDuration"; + public static final String SUSPEND_MAXIMUM_DURATION = "suspendMaximumDuration"; + public static final String SUSPEND_PROGRESSION_FACTOR = "suspendProgressionFactor"; + public static final String RETRY_ERROR_CODES = "retryErrorCodes"; + public static final String RETRY_COUNT = "retryCount"; + public static final String RETRY_DELAY = "retryDelay"; + + public static final String TRACE = "trace"; + public static final String STATISTICS = "statistics"; + public static final String MISCELLANEOUS_DESCRIPTION = "miscellaneousDescription"; + public static final String MISCELLANEOUS_PROPERTIES = "miscellaneousProperties"; + public static final String QUALITY_OF_SERVICE_ADDRESS_OPTION = "qualityServiceAddressOption"; + public static final String QUALITY_OF_SERVICE_ADDRESS_VERSION = "qualityServiceAddressVersion"; + public static final String QUALITY_OF_SERVICE_ADDRESS_SEPARATE_LISTENER = "qualityServiceAddressSeparateListener"; + + public static final String QUALITY_OF_SERVICE_SECURITY_OPTION = "qualityServiceSecurityOption"; + public static final String QUALITY_OF_SERVICE_SECURITY_INBOUND_OUTBOUND_POLICY_OPTION = "qualityServiceSecurityInboundOutboundPolicyOption"; + public static final String QUALITY_OF_SERVICE_SECURITY_INBOUND_POLICY_KEY = "qualityServiceSecurityInboundPolicyKey"; + public static final String QUALITY_OF_SERVICE_SECURITY_OUTBOUND_POLICY_KEY = "qualityServiceSecurityOutboundPolicyKey"; + public static final String QUALITY_OF_SERVICE_SECURITY_POLICY_KEY = "qualityServiceSecurityPolicyKey"; + + public static final String ENDPOINT = "endpoint"; + public static final String HTTP = "http"; + public static final String ENABLE = "enable"; + public static final String URI_TEMPLATE = "uri-template"; + public static final String ENABLE_ADDRESSING = "enableAddressing"; + public static final String ENABLE_SECURITY = "enableSec"; + public static final String SEPARATE_LISTENER = "separateListener"; + public static final String VERSION = "version"; + public static final String POLICY = "policy"; + public static final String INBOUND_POLICY = "inboundPolicy"; + public static final String OUTBOUND_POLICY = "outboundPolicy"; + public static final String TIMEOUT = "timeout"; + public static final String DURATION = "duration"; + public static final String RESPONSE_ACTION = "responseAction"; + public static final String NEVER = "never"; + public static final String SUSPEND_ON_FAILURE = "suspendOnFailure"; + public static final String ERROR_CODES = "errorCodes"; + public static final String INITIAL_DURATION = "initialDuration"; + public static final String MAXIMUM_DURATION = "maximumDuration"; + public static final String PROGRESSION_FACTOR = "progressionFactor"; + public static final String MARK_FOR_SUSPENSION = "markForSuspension"; + public static final String RETRIES_BEFORE_SUSPENSION = "retriesBeforeSuspension"; + public static final String AUTHENTICATION = "authentication"; + public static final String DESCRIPTION = "description"; + public static final String AUTHORIZATION_CODE = "authorizationCode"; + public static final String PASSWORD_CREDENTIALS = "passwordCredentials"; + public static final String CLIENT_CREDENTIALS = "clientCredentials"; + public static final String TOKEN_URL = "tokenUrl"; + public static final String CLIENT_ID = "clientId"; + public static final String CLIENT_SECRET = "clientSecret"; + public static final String USERNAME = "username"; + public static final String PASSWORD = "password"; + public static final String REFRESH_TOKEN = "refreshToken"; + public static final String AUTH_MODE = "authMode"; + public static final String REQUEST_PARAMETERS = "requestParameters"; + public static final String BASIC_AUTH_TAG = "basicAuth"; + public static final String OAUTH_TAG = "oauth"; public static final String SCATTER_MESSAGES = "SCATTER_MESSAGES"; public static final String CONTINUE_FLOW_TRIGGERED_FROM_MEDIATOR_WORKER = "CONTINUE_FLOW_TRIGGERED_FROM_MEDIATOR_WORKER"; } diff --git a/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java b/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java index 97539f8094..b8dd3fa415 100644 --- a/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java +++ b/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java @@ -30,8 +30,11 @@ import org.apache.synapse.config.xml.EntryFactory; import org.apache.synapse.config.xml.EntrySerializer; import org.apache.synapse.config.xml.MultiXMLConfigurationBuilder; +import org.apache.synapse.config.xml.endpoints.EndpointFactory; +import org.apache.synapse.endpoints.Endpoint; import org.apache.synapse.transport.dynamicconfigurations.KeyStoreReloaderHolder; import org.apache.synapse.transport.nhttp.config.SslSenderTrustStoreHolder; +import org.apache.synapse.util.HTTPConnectionUtils; import java.io.File; import java.io.FileInputStream; @@ -89,6 +92,7 @@ public String deploySynapseArtifact(OMElement artifactConfig, String fileName, log.info("LocalEntry named '" + e.getKey() + "' has been deployed from file : " + fileName); handleSSLSenderCertificates(artifactConfig); + deployEndpointsForHTTPConnection(artifactConfig, fileName, properties); return e.getKey(); } else { handleSynapseArtifactDeploymentError("LocalEntry Deployment Failed. The artifact " + @@ -102,6 +106,50 @@ public String deploySynapseArtifact(OMElement artifactConfig, String fileName, return null; } + private void deployEndpointsForHTTPConnection(OMElement artifactConfig, String fileName, Properties properties) { + + OMElement httpInitElement = + artifactConfig.getFirstChildWithName( + new QName(SynapseConstants.SYNAPSE_NAMESPACE, HTTP_CONNECTION_IDENTIFIER)); + if (httpInitElement != null) { + OMElement generatedEndpointElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(httpInitElement); + deployHTTPEndpointForElement(generatedEndpointElement, fileName, properties); + } + } + + private void deployHTTPEndpointForElement(OMElement documentElement, String fileName, Properties properties) { + + try { + Endpoint ep = EndpointFactory.getEndpointFromElement(documentElement, false, properties); + + //Set the car name + ep.setArtifactContainerName(customLogContent); + if (ep != null) { + ep.setFileName((new File(fileName)).getName()); + if (log.isDebugEnabled()) { + log.debug("Endpoint named '" + ep.getName() + + "' has been built from the http connection file " + fileName); + } + ep.init(getSynapseEnvironment()); + if (log.isDebugEnabled()) { + log.debug("Initialized the endpoint : " + ep.getName()); + } + getSynapseConfiguration().addEndpoint(ep.getName(), ep); + if (log.isDebugEnabled()) { + log.debug("Endpoint Deployment from the http connection file : " + fileName + " : Completed"); + } + log.info("Endpoint named '" + ep.getName() + + "' has been deployed from the http connection file : " + fileName); + } else { + handleSynapseArtifactDeploymentError("Endpoint Deployment Failed. The artifact " + + "described in the http connection file " + fileName + " has filed to describe an Endpoint"); + } + } catch (Exception e) { + handleSynapseArtifactDeploymentError("Endpoint Deployment from the http connection file : " + + fileName + " : Failed.", e); + } + } + private void handleSSLSenderCertificates(OMElement element) throws DeploymentException { OMElement httpInitElement = diff --git a/modules/core/src/main/java/org/apache/synapse/util/HTTPConnectionUtils.java b/modules/core/src/main/java/org/apache/synapse/util/HTTPConnectionUtils.java new file mode 100644 index 0000000000..0104249eda --- /dev/null +++ b/modules/core/src/main/java/org/apache/synapse/util/HTTPConnectionUtils.java @@ -0,0 +1,773 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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. + */ + +package org.apache.synapse.util; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; +import org.apache.axiom.om.impl.llom.factory.OMLinkedListImplFactory; +import org.apache.commons.lang.StringUtils; +import org.apache.synapse.SynapseConstants; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * This utility class is responsible for parsing an OMElement to extract + * various HTTP connection parameters and generating an OMElement + * representation of an HTTP Endpoint. + */ +public class HTTPConnectionUtils { + + /** + * Generates an OMElement representation of the HTTP endpoint. + * + * @return the OMElement representing the HTTP endpoint + */ + public static OMElement generateHTTPEndpointOMElement(OMElement connectionOMElement) { + + Map connectionElements = generateConnectionElementsMap(connectionOMElement); + + OMFactory factory = new OMLinkedListImplFactory(); + OMNamespace synapseNS = factory.createOMNamespace("http://ws.apache.org/ns/synapse", ""); + + OMElement endpoint = factory.createOMElement(SynapseConstants.ENDPOINT, synapseNS); + endpoint.addAttribute(SynapseConstants.NAME, + connectionElements.get(SynapseConstants.NAME) + SynapseConstants.ENDPOINT_IDENTIFIER, null); + + OMElement http = factory.createOMElement(SynapseConstants.HTTP, synapseNS); + if (SynapseConstants.ENABLE.equalsIgnoreCase(connectionElements.get(SynapseConstants.TRACE))) { + http.addAttribute(SynapseConstants.TRACE, SynapseConstants.ENABLE, null); + } + if (SynapseConstants.ENABLE.equalsIgnoreCase(connectionElements.get(SynapseConstants.STATISTICS))) { + http.addAttribute(SynapseConstants.STATISTICS, SynapseConstants.ENABLE, null); + } + http.addAttribute(SynapseConstants.URI_TEMPLATE, "{uri.var.base}{+uri.var.path}{+uri.var.query}", null); + + populateEnableAddressingElement(factory, synapseNS, http, connectionElements); + populateEnableSecurityElement(factory, synapseNS, http, connectionElements); + populateTimeoutElement(factory, synapseNS, http, connectionElements); + populateSuspendOnFailureElement(factory, synapseNS, http, connectionElements); + populateMarkForSuspensionElement(factory, synapseNS, http, connectionElements); + populateAuthenticationElement(factory, synapseNS, http, connectionElements); + endpoint.addChild(http); + + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.MISCELLANEOUS_PROPERTIES))) { + List miscellaneousProperties = generateMiscellaneousPropertiesElement( + factory, synapseNS, connectionElements.get(SynapseConstants.MISCELLANEOUS_PROPERTIES)); + for (OMElement property : miscellaneousProperties) { + endpoint.addChild(property); + } + } + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.MISCELLANEOUS_DESCRIPTION))) { + OMElement description = factory.createOMElement(SynapseConstants.DESCRIPTION, synapseNS); + description.setText(connectionElements.get(SynapseConstants.MISCELLANEOUS_DESCRIPTION)); + endpoint.addChild(description); + } + return endpoint; + } + + /** + * Populates the enable security element for the HTTP endpoint configuration. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param http the OMElement representing the HTTP endpoint + * @param connectionElements the map containing the HTTP connection parameters + */ + private static void populateEnableSecurityElement(OMFactory factory, OMNamespace synapseNS, + OMElement http, Map connectionElements) { + + if (SynapseConstants.ENABLE.equalsIgnoreCase( + connectionElements.get(SynapseConstants.QUALITY_OF_SERVICE_SECURITY_OPTION))) { + OMElement enableSecurity = factory.createOMElement(SynapseConstants.ENABLE_SECURITY, synapseNS); + if (SynapseConstants.ENABLE.equalsIgnoreCase( + connectionElements.get( + SynapseConstants.QUALITY_OF_SERVICE_SECURITY_INBOUND_OUTBOUND_POLICY_OPTION))) { + if (StringUtils.isNotEmpty( + connectionElements.get(SynapseConstants.QUALITY_OF_SERVICE_SECURITY_INBOUND_POLICY_KEY))) { + enableSecurity.addAttribute(SynapseConstants.INBOUND_POLICY, + connectionElements.get(SynapseConstants.QUALITY_OF_SERVICE_SECURITY_INBOUND_POLICY_KEY), + null); + } + if (StringUtils.isNotEmpty( + connectionElements.get(SynapseConstants.QUALITY_OF_SERVICE_SECURITY_OUTBOUND_POLICY_KEY))) { + enableSecurity.addAttribute(SynapseConstants.OUTBOUND_POLICY, + connectionElements.get(SynapseConstants.QUALITY_OF_SERVICE_SECURITY_OUTBOUND_POLICY_KEY), + null); + } + } else { + if (StringUtils.isNotEmpty( + connectionElements.get(SynapseConstants.QUALITY_OF_SERVICE_SECURITY_POLICY_KEY))) { + enableSecurity.addAttribute(SynapseConstants.POLICY, + connectionElements.get(SynapseConstants.QUALITY_OF_SERVICE_SECURITY_POLICY_KEY), null); + } + } + http.addChild(enableSecurity); + } + } + + /** + * Populates the enable addressing element for the HTTP endpoint configuration. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param http the OMElement representing the HTTP endpoint + * @param connectionElements the map containing the HTTP connection parameters + */ + private static void populateEnableAddressingElement(OMFactory factory, OMNamespace synapseNS, OMElement http, + Map connectionElements) { + + if (SynapseConstants.ENABLE.equalsIgnoreCase( + connectionElements.get(SynapseConstants.QUALITY_OF_SERVICE_ADDRESS_OPTION))) { + OMElement enableAddressing = factory.createOMElement(SynapseConstants.ENABLE_ADDRESSING, synapseNS); + if (SynapseConstants.ENABLE.equalsIgnoreCase(connectionElements.get( + SynapseConstants.QUALITY_OF_SERVICE_ADDRESS_SEPARATE_LISTENER))) { + enableAddressing.addAttribute(SynapseConstants.SEPARATE_LISTENER, "true", null); + } + if (StringUtils.isNotEmpty(connectionElements.get( + SynapseConstants.QUALITY_OF_SERVICE_ADDRESS_VERSION))) { + enableAddressing.addAttribute(SynapseConstants.VERSION, + connectionElements.get(SynapseConstants.QUALITY_OF_SERVICE_ADDRESS_VERSION), null); + } + http.addChild(enableAddressing); + } + } + + /** + * Populates the authentication element for the HTTP endpoint configuration. + * This method adds the appropriate authentication details (Basic or OAuth) + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param http the OMElement representing the HTTP endpoint + * @param connectionElements the map containing the HTTP connection parameters + */ + private static void populateAuthenticationElement(OMFactory factory, OMNamespace synapseNS, + OMElement http, Map connectionElements) { + + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.AUTH_TYPE))) { + if (SynapseConstants.BASIC_AUTH.equalsIgnoreCase(connectionElements.get(SynapseConstants.AUTH_TYPE))) { + OMElement authentication = factory.createOMElement(SynapseConstants.AUTHENTICATION, synapseNS); + OMElement basicAuth = generateBasicAuthenticationElement(factory, synapseNS, + connectionElements.get(SynapseConstants.USERNAME), + connectionElements.get(SynapseConstants.PASSWORD)); + authentication.addChild(basicAuth); + http.addChild(authentication); + } else if (SynapseConstants.OAUTH.equalsIgnoreCase(connectionElements.get(SynapseConstants.AUTH_TYPE))) { + OMElement authentication = factory.createOMElement(SynapseConstants.AUTHENTICATION, synapseNS); + OMElement oauth = factory.createOMElement(SynapseConstants.OAUTH_TAG, synapseNS); + if (SynapseConstants.OAUTH_GRANT_TYPE_AUTHORIZATION_CODE.equalsIgnoreCase( + connectionElements.get(SynapseConstants.OAUTH_GRANT_TYPE))) { + OMElement authorizationCode = generateOAuthAuthorizationCodeElement(factory, synapseNS, + connectionElements.get(SynapseConstants.REFRESH_TOKEN), + connectionElements.get(SynapseConstants.CLIENT_ID), + connectionElements.get(SynapseConstants.CLIENT_SECRET), + connectionElements.get(SynapseConstants.TOKEN_URL), + connectionElements.get(SynapseConstants.OAUTH_AUTHORIZATION_MODE), + connectionElements.get(SynapseConstants.REQUEST_PARAMETERS)); + oauth.addChild(authorizationCode); + authentication.addChild(oauth); + http.addChild(authentication); + } else if (SynapseConstants.OAUTH_GRANT_TYPE_CLIENT_CREDENTIALS.equalsIgnoreCase( + connectionElements.get(SynapseConstants.OAUTH_GRANT_TYPE))) { + OMElement clientCredentials = generateOAuthClientCredentialsElement(factory, synapseNS, + connectionElements.get(SynapseConstants.CLIENT_ID), + connectionElements.get(SynapseConstants.CLIENT_SECRET), + connectionElements.get(SynapseConstants.TOKEN_URL), + connectionElements.get(SynapseConstants.OAUTH_AUTHORIZATION_MODE), + connectionElements.get(SynapseConstants.REQUEST_PARAMETERS)); + oauth.addChild(clientCredentials); + authentication.addChild(oauth); + http.addChild(authentication); + } else if (SynapseConstants.OAUTH_GRANT_TYPE_PASSWORD.equalsIgnoreCase( + connectionElements.get(SynapseConstants.OAUTH_GRANT_TYPE))) { + OMElement passwordCredentials = generateOAuthPasswordCredentialsElement(factory, synapseNS, + connectionElements.get(SynapseConstants.USERNAME), + connectionElements.get(SynapseConstants.PASSWORD), + connectionElements.get(SynapseConstants.CLIENT_ID), + connectionElements.get(SynapseConstants.CLIENT_SECRET), + connectionElements.get(SynapseConstants.TOKEN_URL), + connectionElements.get(SynapseConstants.OAUTH_AUTHORIZATION_MODE), + connectionElements.get(SynapseConstants.REQUEST_PARAMETERS)); + oauth.addChild(passwordCredentials); + authentication.addChild(oauth); + http.addChild(authentication); + } + } + } + } + + /** + * Populates the mark for suspension element for the HTTP endpoint configuration. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param http the OMElement representing the HTTP endpoint + * @param connectionElements the map containing the HTTP connection parameters + */ + private static void populateMarkForSuspensionElement(OMFactory factory, OMNamespace synapseNS, OMElement http, + Map connectionElements) { + + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.RETRY_ERROR_CODES)) || + StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.RETRY_COUNT)) || + StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.RETRY_DELAY))) { + + OMElement markForSuspension = factory.createOMElement(SynapseConstants.MARK_FOR_SUSPENSION, synapseNS); + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.RETRY_ERROR_CODES))) { + OMElement retryErrorCodes = factory.createOMElement(SynapseConstants.ERROR_CODES, synapseNS); + retryErrorCodes.setText(connectionElements.get(SynapseConstants.RETRY_ERROR_CODES)); + markForSuspension.addChild(retryErrorCodes); + } + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.RETRY_COUNT))) { + OMElement retriesBeforeSuspension = + factory.createOMElement(SynapseConstants.RETRIES_BEFORE_SUSPENSION, synapseNS); + retriesBeforeSuspension.setText(String.valueOf(connectionElements.get(SynapseConstants.RETRY_COUNT))); + markForSuspension.addChild(retriesBeforeSuspension); + } + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.RETRY_DELAY))) { + OMElement retryDelay = factory.createOMElement(SynapseConstants.RETRY_DELAY, synapseNS); + retryDelay.setText(String.valueOf(connectionElements.get(SynapseConstants.RETRY_DELAY))); + markForSuspension.addChild(retryDelay); + } + http.addChild(markForSuspension); + } + } + + /** + * Populates the suspend on failure element for the HTTP endpoint configuration. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param httpEndpointElement the OMElement representing the HTTP endpoint + * @param connectionElements the map containing the HTTP connection parameters + */ + private static void populateSuspendOnFailureElement(OMFactory factory, OMNamespace synapseNS, + OMElement httpEndpointElement, + Map connectionElements) { + + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.SUSPEND_ERROR_CODES)) || + StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.SUSPEND_INITIAL_DURATION)) || + StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.SUSPEND_PROGRESSION_FACTOR)) || + StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.SUSPEND_MAXIMUM_DURATION))) { + + OMElement suspendOnFailure = factory.createOMElement(SynapseConstants.SUSPEND_ON_FAILURE, synapseNS); + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.SUSPEND_ERROR_CODES))) { + OMElement errorCodes = factory.createOMElement(SynapseConstants.ERROR_CODES, synapseNS); + errorCodes.setText(connectionElements.get(SynapseConstants.SUSPEND_ERROR_CODES)); + suspendOnFailure.addChild(errorCodes); + } + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.SUSPEND_INITIAL_DURATION))) { + OMElement initialDuration = factory.createOMElement(SynapseConstants.INITIAL_DURATION, synapseNS); + initialDuration.setText( + String.valueOf(connectionElements.get(SynapseConstants.SUSPEND_INITIAL_DURATION))); + suspendOnFailure.addChild(initialDuration); + } + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.SUSPEND_PROGRESSION_FACTOR))) { + OMElement progressionFactor = factory.createOMElement(SynapseConstants.PROGRESSION_FACTOR, synapseNS); + progressionFactor.setText( + String.valueOf(connectionElements.get(SynapseConstants.SUSPEND_PROGRESSION_FACTOR))); + suspendOnFailure.addChild(progressionFactor); + } + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.SUSPEND_MAXIMUM_DURATION))) { + OMElement maximumDuration = factory.createOMElement(SynapseConstants.MAXIMUM_DURATION, synapseNS); + maximumDuration.setText( + String.valueOf(connectionElements.get(SynapseConstants.SUSPEND_MAXIMUM_DURATION))); + suspendOnFailure.addChild(maximumDuration); + } + httpEndpointElement.addChild(suspendOnFailure); + } + } + + /** + * Populates the timeout element for the HTTP endpoint configuration. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param httpEndpointElement the OMElement representing the HTTP endpoint + * @param connectionElements the map containing the HTTP connection parameters + */ + private static void populateTimeoutElement(OMFactory factory, OMNamespace synapseNS, + OMElement httpEndpointElement, Map connectionElements) { + + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.TIMEOUT_DURATION)) || + StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.TIMEOUT_ACTION))) { + + OMElement timeout = factory.createOMElement(SynapseConstants.TIMEOUT, synapseNS); + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.TIMEOUT_DURATION))) { + OMElement duration = factory.createOMElement(SynapseConstants.DURATION, synapseNS); + duration.setText(String.valueOf(connectionElements.get(SynapseConstants.TIMEOUT_DURATION))); + timeout.addChild(duration); + } + if (StringUtils.isNotEmpty(connectionElements.get(SynapseConstants.TIMEOUT_ACTION)) && + !connectionElements.get(SynapseConstants.TIMEOUT_ACTION).equalsIgnoreCase(SynapseConstants.NEVER)) { + OMElement responseAction = factory.createOMElement(SynapseConstants.RESPONSE_ACTION, synapseNS); + responseAction.setText(connectionElements.get(SynapseConstants.TIMEOUT_ACTION)); + timeout.addChild(responseAction); + } + httpEndpointElement.addChild(timeout); + } + } + + /** + * Generates a list of OMElements representing miscellaneous properties. + * Each property is parsed from a comma-separated string of key:scope:value pairs. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param miscellaneousProperties the comma-separated string of key:scope:value pairs + * @return a list of OMElements representing the miscellaneous properties + */ + private static List generateMiscellaneousPropertiesElement(OMFactory factory, OMNamespace synapseNS, + String miscellaneousProperties) { + + List miscellaneousPropertiesList = new ArrayList<>(); + for (String miscProperty : miscellaneousProperties.split(",")) { + String[] keyScopeValue = miscProperty.split(":"); + if (keyScopeValue.length == 3) { + OMElement property = factory.createOMElement("property", synapseNS); + property.addAttribute("name", keyScopeValue[0].trim(), null); + property.addAttribute("scope", keyScopeValue[1].trim(), null); + property.addAttribute("value", keyScopeValue[2].trim(), null); + miscellaneousPropertiesList.add(property); + } + } + return miscellaneousPropertiesList; + } + + /** + * Generates an OMElement representing the OAuth password credentials grant type. + * This includes the username, password, client ID, client secret, token URL, + * authorization mode, and any additional properties. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param username the username + * @param password the password + * @param clientId the client ID + * @param clientSecret the client secret + * @param tokenUrl the token URL + * @param authMode the authorization mode + * @param oauthAdditionalProperties the additional properties for OAuth authentication + * @return the OMElement representing the OAuth password credentials grant type + */ + private static OMElement generateOAuthPasswordCredentialsElement(OMFactory factory, OMNamespace synapseNS, + String username, String password, String clientId, + String clientSecret, String tokenUrl, + String authMode, + String oauthAdditionalProperties) { + + OMElement passwordCredentials = factory.createOMElement(SynapseConstants.PASSWORD_CREDENTIALS, synapseNS); + + OMElement usernameElement = generateAuthUsernameElement(factory, synapseNS, username); + OMElement passwordElement = generateAuthPasswordElement(factory, synapseNS, password); + OMElement clientIdElement = generateOAuthClientIDElement(factory, synapseNS, clientId); + OMElement clientSecretElement = generateOAuthClientSecretElement(factory, synapseNS, clientSecret); + OMElement tokenUrlElement = generateOAuthTokenUrlElement(factory, synapseNS, tokenUrl); + OMElement authModeElement = generateOAuthAuthorizationModeElement(factory, synapseNS, authMode); + + passwordCredentials.addChild(usernameElement); + passwordCredentials.addChild(passwordElement); + passwordCredentials.addChild(clientIdElement); + passwordCredentials.addChild(clientSecretElement); + passwordCredentials.addChild(tokenUrlElement); + passwordCredentials.addChild(authModeElement); + + if (StringUtils.isNotEmpty(oauthAdditionalProperties)) { + OMElement additionalProperties = + generateOAuthAdditionalPropertiesElement(factory, synapseNS, oauthAdditionalProperties); + passwordCredentials.addChild(additionalProperties); + } + return passwordCredentials; + } + + /** + * Generates an OMElement representing the OAuth client credentials grant type. + * This includes the client ID, client secret, token URL, authorization mode, + * and any additional properties. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param clientId the client ID + * @param clientSecret the client secret + * @param tokenUrl the token URL + * @param authMode the authorization mode + * @param oauthAdditionalProperties the additional properties for OAuth authentication + * @return the OMElement representing the OAuth client credentials grant type + */ + private static OMElement generateOAuthClientCredentialsElement(OMFactory factory, OMNamespace synapseNS, + String clientId, String clientSecret, + String tokenUrl, String authMode, + String oauthAdditionalProperties) { + + OMElement clientCredentials = factory.createOMElement(SynapseConstants.CLIENT_CREDENTIALS, synapseNS); + + OMElement oauthClientId = generateOAuthClientIDElement(factory, synapseNS, clientId); + OMElement oauthClientSecret = generateOAuthClientSecretElement(factory, synapseNS, clientSecret); + OMElement oauthTokenUrl = generateOAuthTokenUrlElement(factory, synapseNS, tokenUrl); + OMElement authorizationMode = generateOAuthAuthorizationModeElement(factory, synapseNS, authMode); + + clientCredentials.addChild(oauthClientId); + clientCredentials.addChild(oauthClientSecret); + clientCredentials.addChild(oauthTokenUrl); + clientCredentials.addChild(authorizationMode); + + if (StringUtils.isNotEmpty(oauthAdditionalProperties)) { + OMElement additionalProperties = + generateOAuthAdditionalPropertiesElement(factory, synapseNS, oauthAdditionalProperties); + clientCredentials.addChild(additionalProperties); + } + return clientCredentials; + } + + /** + * Generates an OMElement representing the OAuth authorization code grant type. + * This includes the refresh token, client ID, client secret, token URL, + * authorization mode, and any additional properties. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param refreshToken the refresh token + * @param clientId the client ID + * @param clientSecret the client secret + * @param tokenUrl the token URL + * @param authMode the authorization mode + * @param oauthAdditionalProperties the additional properties for OAuth authentication + * @return the OMElement representing the OAuth authorization code grant type + */ + private static OMElement generateOAuthAuthorizationCodeElement(OMFactory factory, OMNamespace synapseNS, + String refreshToken, String clientId, + String clientSecret, String tokenUrl, + String authMode, String oauthAdditionalProperties) { + + OMElement authorizationCode = factory.createOMElement(SynapseConstants.AUTHORIZATION_CODE, synapseNS); + + OMElement oauthRefreshToken = generateOAuthRefreshTokenElement(factory, synapseNS, refreshToken); + OMElement oauthClientId = generateOAuthClientIDElement(factory, synapseNS, clientId); + OMElement oauthClientSecret = generateOAuthClientSecretElement(factory, synapseNS, clientSecret); + OMElement oauthTokenUrl = generateOAuthTokenUrlElement(factory, synapseNS, tokenUrl); + OMElement authorizationMode = generateOAuthAuthorizationModeElement(factory, synapseNS, authMode); + + authorizationCode.addChild(oauthRefreshToken); + authorizationCode.addChild(oauthClientId); + authorizationCode.addChild(oauthClientSecret); + authorizationCode.addChild(oauthTokenUrl); + authorizationCode.addChild(authorizationMode); + + if (StringUtils.isNotEmpty(oauthAdditionalProperties)) { + OMElement additionalProperties = + generateOAuthAdditionalPropertiesElement(factory, synapseNS, oauthAdditionalProperties); + authorizationCode.addChild(additionalProperties); + } + return authorizationCode; + } + + /** + * Generates an OMElement representing additional OAuth properties. + * This element contains key-value pairs of additional properties used for OAuth authentication. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @return the OMElement representing the additional OAuth properties + */ + private static OMElement generateOAuthAdditionalPropertiesElement(OMFactory factory, OMNamespace synapseNS, + String oauthAdditionalProperties) { + + OMElement additionalProperties = factory.createOMElement(SynapseConstants.REQUEST_PARAMETERS, synapseNS); + for (String additionalProperty : oauthAdditionalProperties.split(",")) { + String[] keyValue = additionalProperty.split(":"); + if (keyValue.length == 2) { + OMElement parameter = factory.createOMElement("parameter", synapseNS); + parameter.addAttribute("name", keyValue[0].trim(), null); + parameter.setText(keyValue[1].trim()); + additionalProperties.addChild(parameter); + } + } + return additionalProperties; + } + + /** + * Generates an OMElement representing the OAuth authorization mode. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param oauthAuthorizationMode the OAuth authorization mode + * @return the OMElement representing the OAuth authorization mode + */ + private static OMElement generateOAuthAuthorizationModeElement(OMFactory factory, OMNamespace synapseNS, + String oauthAuthorizationMode) { + + OMElement authMode = factory.createOMElement(SynapseConstants.AUTH_MODE, synapseNS); + authMode.setText(oauthAuthorizationMode); + return authMode; + } + + /** + * Generates an OMElement representing the OAuth token URL. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param tokenUrl the token URL + * @return the OMElement representing the OAuth token URL + */ + private static OMElement generateOAuthTokenUrlElement(OMFactory factory, OMNamespace synapseNS, String tokenUrl) { + + OMElement oauthTokenUrl = factory.createOMElement(SynapseConstants.TOKEN_URL, synapseNS); + oauthTokenUrl.setText(tokenUrl); + return oauthTokenUrl; + } + + /** + * Generates an OMElement representing the OAuth client secret. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param clientSecret the client secret + * @return the OMElement representing the OAuth client secret + */ + private static OMElement generateOAuthClientSecretElement(OMFactory factory, OMNamespace synapseNS, + String clientSecret) { + + OMElement oauthClientSecret = factory.createOMElement(SynapseConstants.CLIENT_SECRET, synapseNS); + oauthClientSecret.setText(clientSecret); + return oauthClientSecret; + } + + /** + * Generates an OMElement representing the OAuth client ID. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @return the OMElement representing the OAuth client ID + */ + private static OMElement generateOAuthClientIDElement(OMFactory factory, OMNamespace synapseNS, String clientId) { + + OMElement oauthClientID = factory.createOMElement(SynapseConstants.CLIENT_ID, synapseNS); + oauthClientID.setText(clientId); + return oauthClientID; + } + + /** + * Generates an OMElement representing the OAuth refresh token. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param refreshToken the refresh token + * @return the OMElement representing the OAuth refresh token + */ + private static OMElement generateOAuthRefreshTokenElement(OMFactory factory, OMNamespace synapseNS, + String refreshToken) { + + OMElement oauthRefreshToken = factory.createOMElement(SynapseConstants.REFRESH_TOKEN, synapseNS); + oauthRefreshToken.setText(refreshToken); + return oauthRefreshToken; + } + + /** + * Generates an OMElement representing the basic authentication credentials. + * This element contains the username and password used for basic authentication. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param username the username + * @param password the password + * @return the OMElement representing the basic authentication credentials + */ + private static OMElement generateBasicAuthenticationElement(OMFactory factory, OMNamespace synapseNS, + String username, String password) { + + OMElement basicAuth = factory.createOMElement(SynapseConstants.BASIC_AUTH_TAG, synapseNS); + OMElement usernameElement = generateAuthUsernameElement(factory, synapseNS, username); + OMElement passwordElement = generateAuthPasswordElement(factory, synapseNS, password); + + basicAuth.addChild(usernameElement); + basicAuth.addChild(passwordElement); + return basicAuth; + } + + /** + * Generates an OMElement representing the authentication password. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param password the password + * @return the OMElement representing the authentication password + */ + private static OMElement generateAuthPasswordElement(OMFactory factory, OMNamespace synapseNS, String password) { + + OMElement authPassword = factory.createOMElement(SynapseConstants.PASSWORD, synapseNS); + authPassword.setText(password); + return authPassword; + } + + /** + * Generates an OMElement representing the authentication username. + * + * @param factory the OMFactory used to create OMElements + * @param synapseNS the OMNamespace for the Synapse configuration + * @param username the username + * @return the OMElement representing the authentication username + */ + private static OMElement generateAuthUsernameElement(OMFactory factory, OMNamespace synapseNS, String username) { + + OMElement authUsername = factory.createOMElement(SynapseConstants.USERNAME, synapseNS); + authUsername.setText(username); + return authUsername; + } + + /** + * Generates a map of connection elements from the provided OMElement. + * This method iterates through the child elements of the given OMElement + * and extracts various HTTP connection parameters, storing them in a map. + * + * @param connectionOMElement the OMElement representing the HTTP connection configuration + * @return a map containing the HTTP connection parameters + */ + private static Map generateConnectionElementsMap(OMElement connectionOMElement) { + + HashMap connectionElementsMap = new HashMap<>(); + Iterator connectionElements = connectionOMElement.getChildElements(); + while (connectionElements.hasNext()) { + OMElement connectionElement = (OMElement) connectionElements.next(); + switch (connectionElement.getLocalName()) { + case SynapseConstants.AUTH_TYPE: + connectionElementsMap.put(SynapseConstants.AUTH_TYPE, connectionElement.getText()); + break; + case SynapseConstants.BASIC_CREDENTIALS_USERNAME: + case SynapseConstants.OAUTH_PASSWORD_GRANT_USERNAME: + connectionElementsMap.put(SynapseConstants.USERNAME, connectionElement.getText()); + break; + case SynapseConstants.BASIC_CREDENTIALS_PASSWORD: + case SynapseConstants.OAUTH_PASSWORD_GRANT_PASSWORD: + connectionElementsMap.put(SynapseConstants.PASSWORD, connectionElement.getText()); + break; + case SynapseConstants.OAUTH_AUTHORIZATION_MODE: + connectionElementsMap.put(SynapseConstants.OAUTH_AUTHORIZATION_MODE, connectionElement.getText()); + break; + case SynapseConstants.OAUTH_GRANT_TYPE: + connectionElementsMap.put(SynapseConstants.OAUTH_GRANT_TYPE, connectionElement.getText()); + break; + case SynapseConstants.OAUTH_AUTHORIZATION_GRANT_CLIENT_ID: + case SynapseConstants.OAUTH_CLIENT_CREDENTIALS_GRANT_CLIENT_ID: + case SynapseConstants.OAUTH_PASSWORD_GRANT_CLIENT_ID: + connectionElementsMap.put(SynapseConstants.CLIENT_ID, connectionElement.getText()); + break; + case SynapseConstants.OAUTH_AUTHORIZATION_GRANT_CLIENT_SECRET: + case SynapseConstants.OAUTH_CLIENT_CREDENTIALS_GRANT_CLIENT_SECRET: + case SynapseConstants.OAUTH_PASSWORD_GRANT_CLIENT_SECRET: + connectionElementsMap.put(SynapseConstants.CLIENT_SECRET, connectionElement.getText()); + break; + case SynapseConstants.OAUTH_AUTHORIZATION_GRANT_TOKEN_URL: + case SynapseConstants.OAUTH_CLIENT_CREDENTIALS_GRANT_TOKEN_URL: + case SynapseConstants.OAUTH_PASSWORD_GRANT_TOKEN_URL: + connectionElementsMap.put(SynapseConstants.TOKEN_URL, connectionElement.getText()); + break; + case SynapseConstants.OAUTH_AUTHORIZATION_GRANT_REFRESH_TOKEN: + connectionElementsMap.put(SynapseConstants.REFRESH_TOKEN, connectionElement.getText()); + break; + case SynapseConstants.OAUTH_AUTHORIZATION_GRANT_ADDITIONAL_PROPERTIES: + case SynapseConstants.OAUTH_CLIENT_CREDENTIALS_GRANT_ADDITIONAL_PROPERTIES: + case SynapseConstants.OAUTH_PASSWORD_GRANT_ADDITIONAL_PROPERTIES: + connectionElementsMap.put(SynapseConstants.REQUEST_PARAMETERS, connectionElement.getText()); + break; + case SynapseConstants.TIMEOUT_DURATION: + connectionElementsMap.put(SynapseConstants.TIMEOUT_DURATION, connectionElement.getText()); + break; + case SynapseConstants.TIMEOUT_ACTION: + connectionElementsMap.put(SynapseConstants.TIMEOUT_ACTION, connectionElement.getText()); + break; + case SynapseConstants.SUSPEND_ERROR_CODES: + connectionElementsMap.put(SynapseConstants.SUSPEND_ERROR_CODES, connectionElement.getText()); + break; + case SynapseConstants.SUSPEND_INITIAL_DURATION: + connectionElementsMap.put(SynapseConstants.SUSPEND_INITIAL_DURATION, connectionElement.getText()); + break; + case SynapseConstants.SUSPEND_MAXIMUM_DURATION: + connectionElementsMap.put(SynapseConstants.SUSPEND_MAXIMUM_DURATION, connectionElement.getText()); + break; + case SynapseConstants.SUSPEND_PROGRESSION_FACTOR: + connectionElementsMap.put(SynapseConstants.SUSPEND_PROGRESSION_FACTOR, connectionElement.getText()); + break; + case SynapseConstants.RETRY_ERROR_CODES: + connectionElementsMap.put(SynapseConstants.RETRY_ERROR_CODES, connectionElement.getText()); + break; + case SynapseConstants.RETRY_COUNT: + connectionElementsMap.put(SynapseConstants.RETRY_COUNT, connectionElement.getText()); + break; + case SynapseConstants.RETRY_DELAY: + connectionElementsMap.put(SynapseConstants.RETRY_DELAY, connectionElement.getText()); + break; + case SynapseConstants.NAME: + connectionElementsMap.put(SynapseConstants.NAME, connectionElement.getText()); + break; + case SynapseConstants.TRACE: + connectionElementsMap.put(SynapseConstants.TRACE, connectionElement.getText()); + break; + case SynapseConstants.STATISTICS: + connectionElementsMap.put(SynapseConstants.STATISTICS, connectionElement.getText()); + break; + case SynapseConstants.MISCELLANEOUS_DESCRIPTION: + connectionElementsMap.put(SynapseConstants.MISCELLANEOUS_DESCRIPTION, connectionElement.getText()); + break; + case SynapseConstants.MISCELLANEOUS_PROPERTIES: + connectionElementsMap.put(SynapseConstants.MISCELLANEOUS_PROPERTIES, connectionElement.getText()); + break; + case SynapseConstants.QUALITY_OF_SERVICE_ADDRESS_OPTION: + connectionElementsMap.put(SynapseConstants.QUALITY_OF_SERVICE_ADDRESS_OPTION, + connectionElement.getText()); + break; + case SynapseConstants.QUALITY_OF_SERVICE_ADDRESS_VERSION: + connectionElementsMap.put(SynapseConstants.QUALITY_OF_SERVICE_ADDRESS_VERSION, + connectionElement.getText()); + break; + case SynapseConstants.QUALITY_OF_SERVICE_ADDRESS_SEPARATE_LISTENER: + connectionElementsMap.put(SynapseConstants.QUALITY_OF_SERVICE_ADDRESS_SEPARATE_LISTENER, + connectionElement.getText()); + break; + case SynapseConstants.QUALITY_OF_SERVICE_SECURITY_OPTION: + connectionElementsMap.put(SynapseConstants.QUALITY_OF_SERVICE_SECURITY_OPTION, + connectionElement.getText()); + break; + case SynapseConstants.QUALITY_OF_SERVICE_SECURITY_INBOUND_OUTBOUND_POLICY_OPTION: + connectionElementsMap.put( + SynapseConstants.QUALITY_OF_SERVICE_SECURITY_INBOUND_OUTBOUND_POLICY_OPTION, + connectionElement.getText()); + break; + case SynapseConstants.QUALITY_OF_SERVICE_SECURITY_POLICY_KEY: + connectionElementsMap.put(SynapseConstants.QUALITY_OF_SERVICE_SECURITY_POLICY_KEY, + connectionElement.getText()); + break; + case SynapseConstants.QUALITY_OF_SERVICE_SECURITY_INBOUND_POLICY_KEY: + connectionElementsMap.put(SynapseConstants.QUALITY_OF_SERVICE_SECURITY_INBOUND_POLICY_KEY, + connectionElement.getText()); + break; + case SynapseConstants.QUALITY_OF_SERVICE_SECURITY_OUTBOUND_POLICY_KEY: + connectionElementsMap.put(SynapseConstants.QUALITY_OF_SERVICE_SECURITY_OUTBOUND_POLICY_KEY, + connectionElement.getText()); + break; + default: + // Ignore unknown elements + } + } + return connectionElementsMap; + } +} diff --git a/modules/core/src/test/java/org/apache/synapse/util/HTTPConnectionUtilsTest.java b/modules/core/src/test/java/org/apache/synapse/util/HTTPConnectionUtilsTest.java new file mode 100644 index 0000000000..20efea66e7 --- /dev/null +++ b/modules/core/src/test/java/org/apache/synapse/util/HTTPConnectionUtilsTest.java @@ -0,0 +1,774 @@ +package org.apache.synapse.util; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.impl.builder.StAXOMBuilder; +import org.apache.axiom.om.util.StAXUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import javax.xml.stream.XMLStreamException; + +/** + * Unit tests for the HTTPConnectionUtils class. + * This class contains various test cases to verify the correct generation of OMElements + * for different HTTP endpoint configurations. + */ +public class HTTPConnectionUtilsTest { + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration. + * This test verifies that the generated OMElement matches the expected structure + * for a given HTTP connection configuration. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGeneration() throws XMLStreamException { + + String omElementString = + "\n" + + " https\n" + + " library\n" + + " File\n" + + " BasicCredentials\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " resources:certificates/serverpubliccert.crt\n" + + " 403\n" + + " 1\n" + + " 300\n" + + " 3\n" + + " 20\n" + + " Discard\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "Discard" + + "" + + "" + + "403" + + "1" + + "" + + "" + + "300" + + "3" + + "20" + + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals("Generated OMElement does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration without error handling. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithoutErrorHandling() throws XMLStreamException { + + String omElementString = + "\n" + + " http\n" + + " library\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals("Generated OMElement without error handling properties does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with trace enabled. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithTrace() throws XMLStreamException { + + String omElementString = + "\n" + + " http\n" + + " library\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " enable\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals("Generated OMElement with trace enabled does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with statistics enabled. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithStatistics() throws XMLStreamException { + + String omElementString = + "\n" + + " http\n" + + " library\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " enable\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals("Generated OMElement with statistics enabled does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with description. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithMiscellaneousDescription() throws XMLStreamException { + + String omElementString = + "\n" + + " http\n" + + " library\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " enable\n" + + " hello world\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "hello world" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals("Generated OMElement with description does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with miscellaneous properties. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithMiscellaneousProperties() throws XMLStreamException { + + String omElementString = + "\n" + + " http\n" + + " library\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " enable\n" + + " hello world\n" + + " name1:scope1:value1,name2:scope2:value2,\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "" + + "hello world" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals("Generated OMElement with miscellaneous properties does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with + * quality of service addressing properties. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithQualityOfServiceAddressing() throws XMLStreamException { + + String omElementString = + "\n" + + " http\n" + + " library\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " enable\n" + + " enable\n" + + " final\n" + + " enable\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals("Generated OMElement with quality of service addressing properties does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with + * quality of service security policy. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithQualityOfServiceSecurityPolicy() throws XMLStreamException { + + String omElementString = + "\n" + + " http\n" + + " library\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " enable\n" + + " enable\n" + + " final\n" + + " enable\n" + + " enable\n" + + " samplePolicy\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals("Generated OMElement with quality of service security policy does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with + * quality of service security inbound outbound policy. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithQualityOfServiceSecurityInboundOutboundPolicy() throws XMLStreamException { + + String omElementString = + "\n" + + " http\n" + + " library\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " enable\n" + + " enable\n" + + " final\n" + + " enable\n" + + " enable\n" + + " enable\n" + + " sampleInboundPolicy\n" + + " sampleOutboundPolicy\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals( + "Generated OMElement with quality of service security inbound outbound policy does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with TimeoutAction as Never. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithTimeoutActionNever() throws XMLStreamException { + + String omElementString = + "\n" + + " https\n" + + " library\n" + + " File\n" + + " BasicCredentials\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " resources:certificates/serverpubliccert.crt\n" + + " 403\n" + + " 1\n" + + " 300\n" + + " 3\n" + + " 20\n" + + " Never\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "" + + "403" + + "1" + + "" + + "" + + "300" + + "3" + + "20" + + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals("Generated OMElement with TimeoutAction as Never does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with Basic Authentication. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithBasicAuth() throws XMLStreamException { + + String omElementString = + "\n" + + " https\n" + + " library\n" + + " File\n" + + " Basic Auth\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " resources:certificates/serverpubliccert.crt\n" + + " 403\n" + + " 1\n" + + " 300\n" + + " 3\n" + + " 20\n" + + " Discard\n" + + " admin\n" + + " admin\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "Discard" + + "" + + "" + + "403" + + "1" + + "" + + "" + + "300" + + "3" + + "20" + + "" + + "" + + "" + + "admin" + + "admin" + + "" + + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals("Generated OMElement with Basic Authentication does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with OAuth Authorization Code grant type. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithOAuthAuthorizationCode() throws XMLStreamException { + + String omElementString = + "\n" + + " https\n" + + " library\n" + + " File\n" + + " OAuth\n" + + " Header\n" + + " Authorization Code\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " resources:certificates/serverpubliccert.crt\n" + + " 403\n" + + " 1\n" + + " 300\n" + + " 3\n" + + " 20\n" + + " Discard\n" + + " admin\n" + + " admin\n" + + " admin\n" + + " admin\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "Discard" + + "" + + "" + + "403" + + "1" + + "" + + "" + + "300" + + "3" + + "20" + + "" + + "" + + "" + + "" + + "admin" + + "admin" + + "admin" + + "admin" + + "Header" + + "" + + "" + + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals( + "Generated OMElement with OAuth Authorization Code grant type does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with OAuth Client Credentials grant type. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithOAuthAuthorizationCodeAdditionalProperties() throws XMLStreamException { + + String omElementString = + "\n" + + " https\n" + + " library\n" + + " File\n" + + " OAuth\n" + + " Header\n" + + " Authorization Code\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " resources:certificates/serverpubliccert.crt\n" + + " 403\n" + + " 1\n" + + " 300\n" + + " 3\n" + + " 20\n" + + " Discard\n" + + " admin\n" + + " admin\n" + + " admin\n" + + " admin\n" + + " name1:value1, name2:value2\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "Discard" + + "" + + "" + + "403" + + "1" + + "" + + "" + + "300" + + "3" + + "20" + + "" + + "" + + "" + + "" + + "admin" + + "admin" + + "admin" + + "admin" + + "Header" + + "" + + "value1" + + "value2" + + "" + + "" + + "" + + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals( + "Generated OMElement with OAuth Authorization Code grant type and additional properties does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with OAuth Authorization Code grant type + * including expressions. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithOAuthAuthorizationCodeAndExpressions() throws XMLStreamException { + + String omElementString = + "\n" + + " https\n" + + " library\n" + + " File\n" + + " OAuth\n" + + " Header\n" + + " Authorization Code\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " resources:certificates/serverpubliccert.crt\n" + + " 403\n" + + " 1\n" + + " 300\n" + + " 3\n" + + " 20\n" + + " Discard\n" + + " {$ctx:admin}\n" + + " {$ctx:admin}\n" + + " {$ctx:admin}\n" + + " {$ctx:admin}\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "Discard" + + "" + + "" + + "403" + + "1" + + "" + + "" + + "300" + + "3" + + "20" + + "" + + "" + + "" + + "" + + "{$ctx:admin}" + + "{$ctx:admin}" + + "{$ctx:admin}" + + "{$ctx:admin}" + + "Header" + + "" + + "" + + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals( + "Generated OMElement with OAuth Authorization Code grant type and expressions does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with OAuth Client Credentials grant type. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithOAuthClientCredentials() throws XMLStreamException { + + String omElementString = + "\n" + + " https\n" + + " library\n" + + " File\n" + + " OAuth\n" + + " Header\n" + + " Client Credentials\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " resources:certificates/serverpubliccert.crt\n" + + " 403\n" + + " 1\n" + + " 300\n" + + " 3\n" + + " 20\n" + + " Discard\n" + + " admin\n" + + " admin\n" + + " admin\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "Discard" + + "" + + "" + + "403" + + "1" + + "" + + "" + + "300" + + "3" + + "20" + + "" + + "" + + "" + + "" + + "admin" + + "admin" + + "admin" + + "Header" + + "" + + "" + + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals( + "Generated OMElement with OAuth Client Credentials grant type does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } + + /** + * Tests the generation of an OMElement for an HTTP endpoint configuration with OAuth Password Credentials grant type. + * + * @throws XMLStreamException if an error occurs while parsing the XML + */ + @Test + public void testEndpointOMElementGenerationWithOAuthPassword() throws XMLStreamException { + + String omElementString = + "\n" + + " https\n" + + " library\n" + + " File\n" + + " OAuth\n" + + " Header\n" + + " Password\n" + + " http://jsonplaceholder.typicode.com/posts\n" + + " resources:certificates/serverpubliccert.crt\n" + + " 403\n" + + " 1\n" + + " 300\n" + + " 3\n" + + " 20\n" + + " Discard\n" + + " admin\n" + + " admin\n" + + " admin\n" + + " admin\n" + + " admin\n" + + ""; + String expectedEndpointOMElementString = + "" + + "" + + "" + + "Discard" + + "" + + "" + + "403" + + "1" + + "" + + "" + + "300" + + "3" + + "20" + + "" + + "" + + "" + + "" + + "admin" + + "admin" + + "admin" + + "admin" + + "admin" + + "Header" + + "" + + "" + + "" + + "" + + ""; + InputStream inputStream = new ByteArrayInputStream(omElementString.getBytes(StandardCharsets.UTF_8)); + OMElement documentElement = + new StAXOMBuilder(StAXUtils.createXMLStreamReader(inputStream)).getDocumentElement(); + + OMElement generatedEndpointOMElement = HTTPConnectionUtils.generateHTTPEndpointOMElement(documentElement); + Assert.assertEquals( + "Generated OMElement with OAuth Password Credentials grant type does not match the expected structure", + expectedEndpointOMElementString, generatedEndpointOMElement.toString()); + } +}