/* * Copyright 2018 Tinkoff Bank * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ru.tinkoff.eclair.autoconfigure; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.expression.BeanFactoryResolver; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.SpelCompilerMode; import org.springframework.expression.spel.SpelParserConfiguration; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.oxm.jaxb.Jaxb2Marshaller; import ru.tinkoff.eclair.aop.EclairProxyCreator; import ru.tinkoff.eclair.core.AnnotationDefinitionFactory; import ru.tinkoff.eclair.core.BeanFactoryHelper; import ru.tinkoff.eclair.core.ExpressionEvaluator; import ru.tinkoff.eclair.logger.EclairLogger; import ru.tinkoff.eclair.logger.SimpleLogger; import ru.tinkoff.eclair.printer.*; import ru.tinkoff.eclair.printer.processor.JaxbElementWrapper; import ru.tinkoff.eclair.printer.resolver.AliasedPrinterResolver; import ru.tinkoff.eclair.printer.resolver.PrinterResolver; import java.util.List; import static java.util.Collections.singletonList; import static java.util.Objects.isNull; /** * @author Vyacheslav Klapatnyuk */ @Configuration @EnableConfigurationProperties(EclairProperties.class) public class EclairAutoConfiguration { private final GenericApplicationContext applicationContext; public EclairAutoConfiguration(GenericApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Bean @ConditionalOnMissingBean public EclairLogger simpleLogger() { return new SimpleLogger(); } @Bean @ConditionalOnMissingBean public ExpressionEvaluator expressionEvaluator() { ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(SpelCompilerMode.MIXED, null)); StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); evaluationContext.setBeanResolver(new BeanFactoryResolver(applicationContext)); return new ExpressionEvaluator(expressionParser, evaluationContext); } @Bean public EclairProxyCreator eclairProxyCreator(PrinterResolver printerResolver, List<EclairLogger> orderedLoggers, EclairProperties eclairProperties, ExpressionEvaluator expressionEvaluator) { AnnotationDefinitionFactory annotationDefinitionFactory = new AnnotationDefinitionFactory(printerResolver); EclairProxyCreator eclairProxyCreator = new EclairProxyCreator(applicationContext, annotationDefinitionFactory, orderedLoggers, expressionEvaluator, printerResolver); eclairProxyCreator.setOrder(Ordered.HIGHEST_PRECEDENCE); eclairProxyCreator.setFrozen(false); eclairProxyCreator.setValidate(eclairProperties.isValidate()); return eclairProxyCreator; } @Configuration static class PrinterConfiguration { @Bean @ConditionalOnMissingBean @Order(0) public OverriddenToStringPrinter overriddenToStringPrinter() { return new OverriddenToStringPrinter(); } @Configuration @ConditionalOnClass(Jaxb2Marshaller.class) static class Jaxb2PrinterConfiguration { @Bean @ConditionalOnSingleCandidate(Jaxb2Marshaller.class) @ConditionalOnMissingBean(Jaxb2Printer.class) @Order(100) public Printer jaxb2Printer(ObjectProvider<Jaxb2Marshaller> jaxb2Marshaller) { Jaxb2Marshaller marshaller = jaxb2Marshaller.getObject(); return new Jaxb2Printer(marshaller) .addPreProcessor(new JaxbElementWrapper(marshaller)); } } @Configuration @ConditionalOnClass(ObjectMapper.class) static class JacksonPrinterConfiguration { @Bean @ConditionalOnSingleCandidate(ObjectMapper.class) @ConditionalOnMissingBean @Order(200) public JacksonPrinter jacksonPrinter(ObjectProvider<ObjectMapper> objectMapper) { return new JacksonPrinter(objectMapper.getObject()); } } @Bean @ConditionalOnMissingBean(ignored = OverriddenToStringPrinter.class) @Order(300) public ToStringPrinter toStringPrinter() { return new ToStringPrinter(); } @Bean @ConditionalOnMissingBean public PrinterResolver printerResolver(GenericApplicationContext applicationContext, ObjectProvider<List<Printer>> printersObjectProvider) { List<Printer> orderedPrinters = printersObjectProvider.getIfAvailable(); List<Printer> printers = isNull(orderedPrinters) ? singletonList(PrinterResolver.defaultPrinter) : orderedPrinters; BeanFactoryHelper beanFactoryHelper = BeanFactoryHelper.getInstance(); return new AliasedPrinterResolver( beanFactoryHelper.collectToOrderedMap(applicationContext, Printer.class, printers), beanFactoryHelper.getAliases(applicationContext, Printer.class)); } } }