/*
 * Copyright 2012-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://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.springframework.cloud.function.web.source;

import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext;
import org.springframework.cloud.function.context.FunctionCatalog;
import org.springframework.cloud.function.context.FunctionRegistration;
import org.springframework.cloud.function.context.config.ContextFunctionCatalogInitializer;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.reactive.function.client.WebClient;

/**
 * @author Dave Syer
 * @since 2.0
 *
 */
class FunctionExporterInitializer
		implements ApplicationContextInitializer<GenericApplicationContext> {

	@Override
	public void initialize(GenericApplicationContext context) {
		if (ContextFunctionCatalogInitializer.enabled && context.getEnvironment()
				.getProperty("spring.functional.enabled", Boolean.class, false)
				&& isExporting(context)) {
			registerWebClient(context);
			registerExport(context);
		}
	}

	private void registerWebClient(GenericApplicationContext context) {
		if (context.getBeanFactory().getBeanNamesForType(WebClient.Builder.class, false,
				false).length == 0) {
			context.registerBean(WebClient.Builder.class, () -> WebClient.builder());
		}
	}

	private boolean isExporting(GenericApplicationContext context) {
		if (context.getEnvironment().getProperty("spring.cloud.function.web.export",
				Boolean.class, false)) {
			return true;
		}
		if (ClassUtils.isPresent("org.springframework.web.context.WebApplicationContext",
				getClass().getClassLoader())) {
			if (context instanceof WebApplicationContext
					|| context instanceof ReactiveWebApplicationContext) {
				return false;
			}
		}
		return true;
	}

	private void registerExport(GenericApplicationContext context) {
		context.registerBean(ExporterProperties.class, () -> new ExporterProperties());
		context.registerBean(FunctionExporterAutoConfiguration.class,
				() -> new FunctionExporterAutoConfiguration(
						context.getBean(ExporterProperties.class)));
		if (context.getBeanFactory().getBeanNamesForType(DestinationResolver.class, false,
				false).length == 0) {
			context.registerBean(DestinationResolver.class,
					() -> context.getBean(FunctionExporterAutoConfiguration.class)
							.simpleDestinationResolver());
		}
		if (context.getBeanFactory().getBeanNamesForType(RequestBuilder.class, false,
				false).length == 0) {
			context.registerBean(RequestBuilder.class,
					() -> context.getBean(FunctionExporterAutoConfiguration.class)
							.simpleRequestBuilder(context.getEnvironment()));
		}
		if (context.getEnvironment()
				.getProperty("spring.cloud.function.web.export.source.url") != null) {
			context.registerBean("origin", FunctionRegistration.class,
					() -> context.getBean(FunctionExporterAutoConfiguration.class)
							.origin(context.getBean(WebClient.Builder.class)));
		}
		if (context.getEnvironment()
				.getProperty("spring.cloud.function.web.export.sink.url") != null) {
			context.registerBean(SupplierExporter.class,
					() -> context.getBean(FunctionExporterAutoConfiguration.class)
							.sourceForwarder(context.getBean(RequestBuilder.class),
									context.getBean(DestinationResolver.class),
									context.getBean(FunctionCatalog.class),
									context.getBean(WebClient.Builder.class)));
		}
	}

}

@@ -672,16 +672,105 @@
 ource;%0A%0A
+import org.springframework.boot.web.reactive.context.ConfigurableReactiveWebEnvironment;%0A
 import o
@@ -837,32 +837,32 @@
 icationContext;%0A
-
 import org.sprin
@@ -1256,16 +1256,83 @@
 sUtils;%0A
+import org.springframework.web.context.ConfigurableWebEnvironment;%0A
 import o
@@ -2243,36 +2243,50 @@
 xt context) %7B%0A%09%09
-if (
+Boolean enabled = 
 context.getEnvir
@@ -2293,16 +2293,21 @@
 onment()
+%0A%09%09%09%09
 .getProp
@@ -2344,23 +2344,27 @@
 b.export
-%22,%0A%09%09%09%09
+.enabled%22, 
 Boolean.
@@ -2368,24 +2368,40 @@
 an.class
-, false)
+);%0A%09%09if (enabled != null
 ) %7B%0A%09%09%09r
@@ -2406,20 +2406,23 @@
 %09return 
-true
+enabled
 ;%0A%09%09%7D%0A%09%09
@@ -2587,16 +2587,16 @@
 Context%0A
-
 %09%09%09%09%09%7C%7C 
@@ -2639,24 +2639,182 @@
 ationContext
+%0A%09%09%09%09%09%7C%7C context.getEnvironment() instanceof ConfigurableWebEnvironment%0A%09%09%09%09%09%7C%7C context%0A%09%09%09%09%09%09%09.getEnvironment() instanceof ConfigurableReactiveWebEnvironment
 ) %7B%0A%09%09%09%09retu

Fix test for supplier exporter in functional application