<!--
 ~ Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 ~
 ~ WSO2 Inc. 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.
 -->

        #####################  Define the macros ######################

        #macro ( print_string_if_exist $field $default)
        #if($field && "$field" !="")
        "$field"
        #else
        "$default"
        #end
        #end

        #macro ( draw_endpoint $type $endpoint_config )

        #set( $endpointClass = $endpoint_config.get("endpoint_type") )
        #set( $endpoints = $endpoint_config.get("${type}_endpoints"))
        #set( $ep_key = "${endpointKey}_API${type}Endpoint")
        #set( $endpointsecurity = $endpoint_security.get("${type}"))
        ## IF endpoint secured
        #if($endpointsecurity.enabled)
        #if($endpointsecurity.type == "basic" || $endpointsecurity.type == "BASIC")
        #if($isSecureVaultEnabled)
<property xmlns="http://ws.apache.org/ns/synapse" name="password" expression="wso2:vault-lookup('$endpointsecurity.alias')"/>
<property xmlns="http://ws.apache.org/ns/synapse" name="unpw" expression="fn:concat('$endpointsecurity.username',':',get-property('password'))"/>
<property xmlns="http://ws.apache.org/ns/synapse" name="Authorization" expression="fn:concat('Basic ', base64Encode(get-property('unpw')))" scope="transport"/>
        #else
<property xmlns="http://ws.apache.org/ns/synapse" name="Authorization" expression="fn:concat('Basic ', '$endpointsecurity.base64EncodedPassword')" scope="transport"/>
        #end
        #else
        #if($endpointsecurity.type == "digest" || $endpointsecurity.type == "DIGEST")
<property xmlns="http://ws.apache.org/ns/synapse" name="UNAMEPASSWORD" value="$util.escapeXml($endpointsecurity.base64EncodedPassword)" type="STRING"/>
<property name="BACKEND_URL" value="$util.escapeXml($endpoints.get("url"))"/>
<property name="POSTFIX" expression="get-property('axis2', 'REST_URL_POSTFIX')"/>
<property name="HTTP_METHOD" expression="get-property('axis2', 'HTTP_METHOD')"/>
<property name="POST_TO_URI" value="true" scope="axis2"/>
<property name="MessageType" expression="get-property('axis2', 'messageType')"/>

<enrich>
<source type="body" clone="true"/>
<target type="property" property="MessageBody"/>
</enrich>

<call>
<endpoint key="$ep_key"/>
</call>

<class name="org.wso2.carbon.apimgt.gateway.mediators.DigestAuthMediator"/>

<property name="Authorization" expression="get-property('AuthHeader')" scope="transport"/>
<property name="messageType" expression="get-property('MessageType')" scope="axis2"/>
<property name="HTTP_METHOD" expression="get-property('HTTP_METHOD')" scope="axis2"/>
<property name="REST_URL_POSTFIX" expression="$ctx:POSTFIX" scope="axis2"/>
<property name="POST_TO_URI" value="true" scope="axis2"/>

<enrich>
<source type="property" property="MessageBody" clone="true"/>
<target type="body"/>
</enrich>
        #else
        #if($endpointsecurity.type == "oauth" || $endpointsecurity.type == "OAUTH")
<class name="org.wso2.carbon.apimgt.gateway.mediators.oauth.OAuthMediator">
<property name="uniqueIdentifier" value="$util.escapeXml($endpointsecurity.uniqueIdentifier)" type="STRING"/>
<property name="tokenEndpointUrl" value="$util.escapeXml($endpointsecurity.tokenUrl)" type="STRING"/>
<property name="clientId" value="$util.escapeXml($endpointsecurity.clientId)" type="STRING"/>
<property name="grantType" value="$util.escapeXml($endpointsecurity.grantType)" type="STRING"/>
<property name="customParameters" value="$util.escapeXml($endpointsecurity.customParameters)" type="STRING"/>
#if($isSecureVaultEnabled)
<property name="clientSecret" expression="wso2:vault-lookup('$endpointsecurity.clientSecretAlias')" type="STRING"/>
#else
<property name="clientSecret" value="$util.escapeXml($endpointsecurity.clientSecret)" type="STRING"/>
#end
#if($endpointsecurity.grantType == "password" || $endpointsecurity.grantType == "PASSWORD")
<property name="username" value="$util.escapeXml($endpointsecurity.username)" type="STRING"/>
#if($isSecureVaultEnabled)
<property name="password" expression="wso2:vault-lookup('$endpointsecurity.passwordAlias')" type="STRING"/>
#else
<property name="password" value="$util.escapeXml($endpointsecurity.password)" type="STRING"/>
#end
#end
</class>
        #end
        #end
        #end
        #end
<send>

## If endpoint is http
#if ($endpointClass == "http")
<endpoint xmlns="http://ws.apache.org/ns/synapse" key="$ep_key"/>
#elseif ($endpointClass == "ws")
#set($resourceKey = $topicMappings.get("$topic").get("resourceKey"))
#set($wsEndpointName = "${ep_key}_${resourceKey}")
<endpoint xmlns="http://ws.apache.org/ns/synapse" key="$wsEndpointName"/>
#elseif ($endpointClass == "address")
<endpoint xmlns="http://ws.apache.org/ns/synapse" key="$ep_key"/>
#elseif ($endpointClass == "wsdl")
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="$ep_name">
    #if (${type} == "production")
    <wsdl uri="$util.escapeXml($endpoints.get("url"))" service="$!endpoint_config.get("wsdlendpointService")" port="$!endpoint_config.get("wsdlendpointPort")">
    #timeout()
</wsdl>
#else
<wsdl uri="$util.escapeXml($endpoints.get("url"))" service="$!endpoint_config.get("wsdlendpointServiceSandbox")" port="$!endpoint_config.get("wsdlendpointPortSandbox")">
#timeout()
</wsdl>
        #end
<property name="ENDPOINT_ADDRESS" value="$util.escapeXml($endpoints.get("url"))"/>
        </endpoint>
        #elseif ($endpointClass == "failover")
        #set( $failover_endpoints = $endpoint_config.get("${type}_failovers"))
<endpoint xmlns="http://ws.apache.org/ns/synapse" key="$ep_key"/>
        #elseif ($endpointClass == "load_balance")
<endpoint xmlns="http://ws.apache.org/ns/synapse" key="$ep_key"/>
        #elseif ($endpointClass == "default")
<endpoint key="$ep_key"/>
        #end
        </send>
        #end

        ######################## End of Macros ######################################


<api xmlns="http://ws.apache.org/ns/synapse"
     name="$!apiName"
     context="$!apiContext"
     version="$!apiVersion"
     transports="$!transport"
     version-type="context"
        #if( $apiType == 'WS' )
        binds-to="WebSocketInboundEndpoint, SecureWebSocketEP"
        #elseif( $apiType == 'GRAPHQL' )
            #if( $isSubscriptionAvailable )
        binds-to="WebSocketInboundEndpoint, SecureWebSocketEP, default"
            #end
        #end
        >
        #set( $originalEndPointConfig = $endpoint_config )
        #if( $apiIsBlocked )
        ## if API is blocked send the API Block message
<resource methods="GET POST PUT DELETE PATCH" url-mapping="/*" faultSequence=#print_string_if_exist($faultSequence "fault")>
<inSequence>
<payloadFactory>
    <format>
        <am:fault xmlns:am="http://wso2.org/apimanager">
            <am:code>700700</am:code>
            <am:message>API blocked</am:message>
            <am:description>This API has been blocked temporarily. Please try again later or contact the system administrators.</am:description>
        </am:fault>
    </format>
</payloadFactory>
<property name="HTTP_SC" value="503" scope="axis2"/>
<property name="RESPONSE" value="true"/>
<property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
<header name="To" action="remove"/>
<send/>
</inSequence>
        </resource>
        #else
            ## api not blocked
            #set ( $resourceNo = 0 )
            #foreach( $resource in $resources )
                #set( $isGQLWSResource = false )
                #set( $endpoint_config = $originalEndPointConfig )

<resource xmlns="http://ws.apache.org/ns/synapse"
                #if( $resource.getUriTemplate().contains("{") ||
                    ($resource.getUriTemplate().contains("*") && !$resource.getUriTemplate().endsWith("/*")) )
        uri-template="$util.escapeXml($resource.getUriTemplate())"
                    #set( $topic= "$util.escapeXml($resource.getUriTemplate())" )
                #else
        url-mapping="$resource.getUriTemplate()"
                    #set( $topic= "$resource.getUriTemplate()" )
                #end

                #if( $isSubscriptionAvailable )
                    #if( $resource.getMethodsAsString() == "" )
                        #set( $isGQLWSResource = true )
        binds-to="WebSocketInboundEndpoint, SecureWebSocketEP"
                    #else
        binds-to="default"
                         #set( $isGQLWSResource = false )
                    #end
                #end

                #if( $apiType == 'SSE' )
                    ## resources are always GET in SSE
        methods="GET"
                #elseif( $apiType != 'WS' && !$isGQLWSResource )
                    ## methods are not applicable for WS
        methods="$resource.getMethodsAsString()"
                #end

        faultSequence=#print_string_if_exist($faultSequence "fault")>
<inSequence>

                ## check and set response caching
                #if( $responseCacheEnabled )
<cache scope="per-host" collector="false" hashGenerator="org.wso2.carbon.mediator.cache.digest.HttpRequestHashGenerator" timeout="$!responseCacheTimeOut">
    <implementation type="memory" maxSize="500"/>
    <onCacheHit>
        <property name="api.analytics.cacheHit" value="true" scope="default"/>
        <respond/>
    </onCacheHit>
</cache>
                #end
<property name="api.ut.backendRequestTime" expression="get-property('SYSTEM_TIME')"/>
                #if( $isSoapToRestMode )
<property name="HTTP_METHOD" value="POST" scope="axis2" type="STRING"/>
                    #foreach( $uri in $in_sequences.get("$resource.getUriTemplate()").keySet() )
$in_sequences.get("$resource.getUriTemplate()").get($uri)
                    #end
                #end
##############  define the filter based on environment type production only, sandbox only , hybrid ############

                ##If graphql api
                #if ( $endpoint_config.get("endpoint_type") == "graphql" )
                    #if( $isGQLWSResource )
                        #set( $endpoint_config = $endpoint_config.get("ws") )
                    #else
                        #set( $endpoint_config = $endpoint_config.get("http") )
                    #end
                #end

                #if( ($environmentType == 'sandbox') || ($environmentType =='hybrid'
                    && !$endpoint_config.get("production_endpoints")) )
                    #set( $filterRegex = "SANDBOX" )
                #else
                    #set( $filterRegex = "PRODUCTION" )
                #end
                ## AWS Lambda: start
                #if( $endpoint_config.get("endpoint_type") == 'awslambda' )
                    #set( $accessKey = $!{endpoint_config.get("amznAccessKey")} )
                    #set( $secretKey = $!{endpoint_config.get("amznSecretKey")} )
                    #set( $region = $!{endpoint_config.get("amznRegion")} )
                    #set( $roleArn = $!{endpoint_config.get("amznRoleArn")} )
                    #set( $roleSessionName = $!{endpoint_config.get("amznRoleSessionName")} )
                    #set( $roleRegion = $!{endpoint_config.get("amznRoleRegion")} )
                    #set( $resourceName = $!{resource.getAmznResourceName()} )
                    #set( $resourceTimeout = $!{resource.getAmznResourceTimeout()} )
                    #set( $isContentEncodingEnabled = $!{resource.isAmznResourceContentEncoded()} )
<class name="org.wso2.carbon.apimgt.gateway.mediators.AWSLambdaMediator">
                    #if( $accessKey != '' )
    <property name="accessKey" value="$accessKey"/>
                    #end
                    #if( $isSecureVaultEnabled )
    <property name="secretKey" expression="wso2:vault-lookup('$endpoint_config.get('awsAlias')')" type="STRING"/>
                    #else
                        #if( $secretKey != '' )
    <property name="secretKey" value="$secretKey"/>
                        #end
                    #end
                    #if( $region != '' )
    <property name="region" value="$region"/>
                    #end
                    #if( $roleArn != '' )
    <property name="roleArn" value="$roleArn"/>
                    #end
                    #if( $roleSessionName != '' )
    <property name="roleSessionName" value="$roleSessionName"/>
                    #end
                    #if( $roleRegion != '' )
    <property name="roleRegion" value="$roleRegion"/>
                    #end
                    #if( $resourceName != '' )
    <property name="resourceName" value="$resourceName"/>
                    #end
                    #if( $resourceTimeout != '' )
    <property name="resourceTimeout" value="$resourceTimeout"/>
                    #end
                    #if( $isContentEncodingEnabled != '' )
    <property name="isContentEncodingEnabled" value="$isContentEncodingEnabled"/>
                    #end
</class>
<loopback />
                ## AWS Lambda: end
                #else
                    #if( $apiIsOauthProtected || $apiIsApiKeyProtected || $apiIsBasicAuthProtected )
<filter source="$ctx:AM_KEY_TYPE" regex="$filterRegex">
    <then>
                    #end
                    #if( ($environmentType == 'sandbox') || ($environmentType =='hybrid'
                        && ! $endpoint_config.get("production_endpoints")) )
                        #draw_endpoint( "sandbox" $endpoint_config )
                    #else
                        #draw_endpoint( "production" $endpoint_config )
                    #end
                    #if( $apiIsOauthProtected || $apiIsApiKeyProtected || $apiIsBasicAuthProtected )
    </then>
    <else>
                        #if( $environmentType !='hybrid' )
        <payloadFactory>
            <format>
                <error xmlns="">
                            #if( $environmentType == 'production' )
                    <message>Sandbox Key Provided for Production Gateway</message>
                            #elseif( $environmentType == 'sandbox' )
                    <message>Production Key Provided for Sandbox Gateway</message>
                            #end
                </error>
            </format>
        </payloadFactory>
        <property name="ContentType" value="application/xml" scope="axis2"/>
        <property name="RESPONSE" value="true"/>
        <header name="To" action="remove"/>
        <property name="HTTP_SC" value="401" scope="axis2"/>
        <property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
        <send/>
                        #else
                            #if( $endpoint_config.get("production_endpoints")
                                && $endpoint_config.get("sandbox_endpoints") )
                                #draw_endpoint( "sandbox" $endpoint_config )
                            #elseif( $endpoint_config.get("production_endpoints") )
        <sequence key="_sandbox_key_error_"/>
                            #elseif( $endpoint_config.get("sandbox_endpoints") )
        <sequence key="_production_key_error_"/>
                            #end
                        #end
    </else>
</filter>
                    #end
                #end
</inSequence>
<outSequence>
                #if( $isSoapToRestMode )
                    #foreach( $uri in $out_sequences.get("$resource.getUriTemplate()").keySet() )
$out_sequences.get("$resource.getUriTemplate()").get($uri)
                    #end
                #end
                ## check and set response caching
                #if( $responseCacheEnabled )
<cache scope="per-host" collector="true"/>
                #end
                #if( $endpointsecurity.type == "oauth" || $endpointsecurity.type == "OAUTH" )
<class name="org.wso2.carbon.apimgt.gateway.mediators.oauth.OAuthResponseMediator"/>
                #end
<send/>
</outSequence>
        </resource>
                #set ($resourceNo = $resourceNo + 1 )
            #end  ## end of resource iterator
            ## print the handlers
            #if( $handlers.size() > 0 )
<handlers xmlns="http://ws.apache.org/ns/synapse">
                #foreach( $handler in $handlers )
<handler xmlns="http://ws.apache.org/ns/synapse" class="$handler.className">
                    #if($handler.hasProperties())
                        #set ($map = $handler.getProperties() )
                        #foreach($property in $map.entrySet())
    <property name="$!property.key" value="$!property.value"/>
                        #end
                    #end
</handler>
                #end
                ## check and set enable schema validation
                #if($enableSchemaValidation)
<handler class="org.wso2.carbon.apimgt.gateway.handlers.security.SchemaValidator"/>
                #end
</handlers>
            #end
        #end
        ## end of apiIsBlocked check
        #if($apiType != 'WS')
<handlers>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler">
    <property name="inline" value="INLINE"/>
</handler>
</handlers>
        #end
</api>
        <!--$endpoint_security-->