[#ftl attributes={"generated.type":"blueprint"}]
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
           xmlns:camelcxf="http://camel.apache.org/schema/blueprint/cxf"
           xmlns:cxf="http://cxf.apache.org/blueprint/core"
           xsi:schemaLocation="
             http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
             http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
             ">
<!--
	
	INFO: 
	   
	factoryId: openapi-based-rest-service-public
	factoryType: entaxy.runtime.service
	outputType: init 
	properties:
	[#list properties?keys as key]
		[=key]
	[/#list]
 -->

	[#if properties.authorizationType != "NONE" && properties.displayServiceSchema]
		<bean id="publicOpenApiSchemaInterceptor" class="ru.entaxy.platform.services.runtime.interceptor.PublicOpenApiSchemaInterceptor">
		</bean>
	[#else]
		<!-- use default behavior -->
	[/#if]

    [#if properties.authorizationType == "JAAS"]
	   <bean id="jaasLoginInterceptor" class="org.apache.cxf.interceptor.security.JAASLoginInterceptor">
		   <property name="contextName" value="[=properties.authorizationRealm]" />
		   <property name="roleClassifier" value="RolePrincipal"/>
		   <property name="roleClassifierType" value="classname"/>
   		   <property name="allowAnonymous" value="false"/>
		   <property name="allowNamedPrincipals" value="true"/>
	   </bean>     
	   <bean id="resolveProfileNameInterceptor" class="ru.entaxy.platform.services.runtime.interceptor.ResolveProfileNameInterceptor">
	   </bean>
	   <bean id="resolveLoginInterceptor" class="ru.entaxy.platform.services.runtime.interceptor.ResolveLoginInterceptor" />
		[#if properties.restrictByRoles]
		<bean id="simpleAuthorizingInterceptor" class="org.apache.cxf.interceptor.security.SimpleAuthorizingInterceptor">
		   <property name="methodRolesMap">
		      <map>
		      	<!-- NOT IMPLEMENTED YET -->
		        <!-- no wildcard support, names need to match exactly -->
		        <!-- entry key="addNumbers" value="ROLE_USER ROLE_ADMIN"/>
		        <entry key="divideNumbers" value="ROLE_ADMIN"/ -->
		      </map>
		   </property>
		   <!-- its possible to define global roles that apply to all WSDL operations not listed above -->
		   <property name="globalRoles" value="[=properties.globalRoles]"/>
		</bean>
		[/#if]
	[/#if]

	[#if properties.authorizationType == "OAUTH STAND ALONE"]
		<bean id="jwtAuthzFilter" class="ru.entaxy.platform.core.support.runtime.cxf.jose.ExtJwtAuthenticationFilter">
			<property name="validateAudience" value="[=properties.jwtAuthzFilterValidateAudience]"/>
			<property name="roleClaim" value="[=properties.jwtAuthzFilterRoleClaim]"/>
			<property name="regexp" value="[=properties.jwtAuthzFilterRegexp]"/>
		</bean>

		[#if properties.restrictByRoles]
			<bean id="authorizationInterceptor" class="org.apache.cxf.interceptor.security.SimpleAuthorizingInterceptor">
				<!-- its possible to define global roles that apply to all WSDL operations not listed above -->
				<property name="globalRoles" value="[=properties.globalRoles]"/>
			</bean>
		[/#if]
	[/#if]

	[#if properties.authorizationType == "OAUTH INTROSPECT"]
		<camelcxf:rsClient id="tokenServiceClient" serviceClass="org.apache.cxf.jaxrs.client.WebClient"
						   address="[=properties.introspectAddress]">
			<camelcxf:headers>
				<entry key="Accept" value="[=properties.introspectAccept]"/>
				<entry key="Content-Type" value="[=properties.introspectContentType]"/>
			</camelcxf:headers>
			<camelcxf:properties>
				<entry key="http.receive.timeout" value="[=properties.introspectHttpReceiveTimeout]"/>
			</camelcxf:properties>
			<camelcxf:providers>
				<ref component-id="jsonProvider"/>
			</camelcxf:providers>
			<camelcxf:outInterceptors>
			<ref component-id="authInterceptor"/>
			</camelcxf:outInterceptors>
		</camelcxf:rsClient>

		<bean id="authInterceptor" class="ru.entaxy.platform.core.support.runtime.cxf.BasicAuthenticationInterceptor">
			<property name="login" value="[=properties.introspectAuthorizationLogin]"/>
			<property name="password" value="[=properties.introspectAuthorizationPasswordVault]"/>
		</bean>

		<bean id="rsClient"
			  class="ru.entaxy.platform.core.support.runtime.cxf.EntaxyWebClient" factory-ref="tokenServiceClient"
			  factory-method="create" />

		<bean id="tokenValidator" class="org.apache.cxf.rs.security.oauth2.filters.AccessTokenIntrospectionClient">
			<property name="tokenValidatorClient" ref="rsClient"/>
		</bean>

		<bean id="oauthFilter" class="ru.entaxy.platform.core.support.runtime.cxf.security.oauth2.filters.DisplaySchemaOAuthRequestFilter">
			<property name="tokenValidator" ref="tokenValidator"/>
			<property name="audienceIsEndpointAddress" value="[=properties.audienceIsEndpointAddress]"/>
		</bean>
	[/#if]


    <!-- JAXRS providers -->
	<bean id="jsonProviderFactory" class="ru.entaxy.platform.core.support.runtime.jackson.JacksonJsonProviderFactory">
		<property name="addJodaModule" value="true"/>
		<property name="acceptSingleValueAsArray" value="true"/>
		<property name="failOnUnknownProperties" value="false"/>
	</bean>
	<bean id="jsonProvider" factory-ref="jsonProviderFactory" factory-method="create"/>
	<!-- CXF OpenApiFeature -->
    <bean id="openApiFeature" class="org.apache.cxf.jaxrs.openapi.OpenApiFeature">
        <property name="runAsFilter" value="true" />
        <property name="useContextBasedConfig" value="true" />
        <property name="scan" value="true" />
    </bean> 
    
    <!-- CXF Bus -->
    <cxf:bus bus="cxf-local-[=objectId]" name="cxf-local-[=objectId]">
        <cxf:properties key-type="java.lang.String" value-type="java.lang.Object">
            <entry key="org.apache.cxf.common.util.ClassUnwrapper" value-ref="class-unwrapper-[=objectId]" />
        </cxf:properties>
    </cxf:bus>

	[#if properties._serviceMetadata.classes.apis??]	
	[#list 0..properties._serviceMetadata.classes.apis?size-1 as i]
	<bean id="proxy-bean-[=objectId]-[=i]" activation="eager" class="ru.entaxy.platform.core.support.runtime.cxf.EntaxyCxfServiceClassProxyBean">
		<property name="realClassName" value="[=properties._serviceMetadata.classes.apis[i]]"></property>
	</bean>	
	[/#list]
	[/#if]

	<bean id="class-unwrapper-[=objectId]" activation="eager" class="ru.entaxy.platform.core.support.runtime.cxf.EntaxyCxfClassResourceUnwrapper" 
			init-method="activate">
		<property name="resourceFolders">
			<list value-type="java.lang.String">
				<value>service-resources:[=properties._serviceMetadata.serviceResourcesRoot]/[=properties._serviceMetadata.classes.folder]/</value>
			</list>
		</property>
		<property name="useCache" value="true"></property>
		<property name="bus" ref="cxf-local-[=objectId]"></property>
		<property name="bundleContext" ref="blueprintBundleContext"></property>
	</bean>

	[#assign finalAddress=properties.address]
	[#if !finalAddress?starts_with('http://') && !finalAddress?starts_with('https://')]
		[#if !finalAddress?starts_with('/')]
			[#assign finalAddress='/'+properties.address]
		[/#if]
	[/#if]
	
    <camelcxf:rsServer id="[=objectId]-rs-server"
                       address="[=finalAddress]"
                       loggingFeatureEnabled="true" 
                       loggingSizeLimit="50"
                       bus="cxf-local-[=objectId]">
		<camelcxf:serviceBeans>
		[#if properties._serviceMetadata.classes.apis??]	
		[#list 0..properties._serviceMetadata.classes.apis?size-1 as i]
			<ref component-id="proxy-bean-[=objectId]-[=i]"/>
		[/#list]
		[/#if]
		</camelcxf:serviceBeans>   
		<camelcxf:providers>
			<ref component-id="jsonProvider"/>
		[#if properties.authorizationType == "OAUTH STAND ALONE"]
			<ref component-id="jwtAuthzFilter"/>
		[/#if]
		[#if properties.authorizationType == "OAUTH INTROSPECT"]
			<ref component-id="oauthFilter" />
		[/#if]
		</camelcxf:providers>
		<camelcxf:features>
			<ref component-id="openApiFeature"/>
		</camelcxf:features>
        <camelcxf:inInterceptors>
		[#if properties.displayServiceSchema]
			<ref component-id="publicOpenApiSchemaInterceptor" />
		[#else]
			<!-- default behavior -->
		[/#if]
	[#if properties.authorizationType == "JAAS"]
        	<ref component-id="jaasLoginInterceptor" />
		[#if properties.restrictByRoles]
			<ref component-id="simpleAuthorizingInterceptor" />
		[/#if]
        	<ref component-id="resolveProfileNameInterceptor" />
        	<ref component-id="resolveLoginInterceptor"/>
    [/#if]
	[#if properties.authorizationType == "OAUTH STAND ALONE" && properties.restrictByRoles]
			<ref component-id="authorizationInterceptor"/>
	[/#if]
        </camelcxf:inInterceptors>
		[#if properties.jwtKeystore??]
		<camelcxf:properties>
			<entry key="rs.security.signature.in.properties"
				   value="[=properties.jwtKeystore].data/$[=properties.jwtAlias].properties"/>
		</camelcxf:properties>
		[/#if]
    </camelcxf:rsServer>

	<bean id="entaxyObjectMapper" class="ru.entaxy.platform.core.support.runtime.jackson.EntaxyObjectMapper"/>

	<camelContext id="openapi-[=objectId]-context" xmlns="http://camel.apache.org/schema/blueprint">

        <route id="[=objectId]-cxf-rs-endpoint" streamCache="true">
            <from uri="cxfrs:bean:[=objectId]-rs-server?bindingStyle=SimpleConsumer"/>
            <setHeader name="ENTAXY_EndpointName">
                <simple>[=objectId]</simple>
            </setHeader>
            <setHeader name="NTX_ERROR_HANDLER_SYNC_TYPE">
                <constant>application/json</constant>
            </setHeader>

		[#if properties.isValidate?? && properties.isValidate]
			<to uri="bean-validator:validation"/>
		[/#if]
		[#if properties.resultType?? && properties.resultType == "ORIGIN"]
			<marshal>
				<json library="Jackson" autoDiscoverObjectMapper="true"/>
			</marshal>
		[/#if]

			[#include "templates:service-components/generateLoggingKey.ftl"]

            <to uri="direct:[=objectId]-operation-router" />

			[#if properties.removeAllHeadersBeforeAnswering]
				<removeHeaders pattern="*"/>
			[/#if]
			<removeProperties pattern="NTX.+|ENTAXY.+"/>
			<removeHeaders pattern="NTX.+|ENTAXY.+"/>
		</route>
        
    </camelContext>

</blueprint> 
