1 /*
2  *
3  *  * Copyright 2019-2020 the original author or authors.
4  *  *
5  *  * Licensed under the Apache License, Version 2.0 (the "License");
6  *  * you may not use this file except in compliance with the License.
7  *  * You may obtain a copy of the License at
8  *  *
9  *  *      https://www.apache.org/licenses/LICENSE-2.0
10  *  *
11  *  * Unless required by applicable law or agreed to in writing, software
12  *  * distributed under the License is distributed on an "AS IS" BASIS,
13  *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  * See the License for the specific language governing permissions and
15  *  * limitations under the License.
16  *
17  */

18
19 package org.springdoc.webmvc.core;
20
21 import java.util.List;
22 import java.util.Optional;
23
24 import io.swagger.v3.oas.models.Operation;
25 import org.springdoc.core.AbstractRequestBuilder;
26 import org.springdoc.core.GenericParameterBuilder;
27 import org.springdoc.core.GenericResponseBuilder;
28 import org.springdoc.core.OpenAPIBuilder;
29 import org.springdoc.core.OperationBuilder;
30 import org.springdoc.core.PropertyResolverUtils;
31 import org.springdoc.core.RequestBodyBuilder;
32 import org.springdoc.core.ReturnTypeParser;
33 import org.springdoc.core.SecurityOAuth2Provider;
34 import org.springdoc.core.SpringDocConfigProperties;
35 import org.springdoc.core.customizers.OpenApiCustomiser;
36 import org.springdoc.core.customizers.OperationCustomizer;
37 import org.springdoc.core.customizers.ParameterCustomizer;
38 import org.springdoc.webmvc.api.ActuatorProvider;
39 import org.springdoc.webmvc.api.OpenApiResource;
40
41 import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
42 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
43 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
44 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
45 import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
46 import org.springframework.context.annotation.Bean;
47 import org.springframework.context.annotation.Configuration;
48 import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
49 import org.springframework.web.method.HandlerMethod;
50 import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
51
52 import static org.springdoc.core.Constants.DEFAULT_GROUP_NAME;
53 import static org.springdoc.core.Constants.SPRINGDOC_ENABLED;
54 import static org.springdoc.core.Constants.SPRINGDOC_SHOW_ACTUATOR;
55
56 @Configuration
57 @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
58 @ConditionalOnProperty(name = SPRINGDOC_ENABLED, matchIfMissing = true)
59 public class SpringDocWebMvcConfiguration {
60
61     @Bean
62     @ConditionalOnMissingBean
63     OpenApiResource openApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequestBuilder requestBuilder,
64             GenericResponseBuilder responseBuilder, OperationBuilder operationParser,
65             RequestMappingInfoHandlerMapping requestMappingHandlerMapping,
66             Optional<ActuatorProvider> servletContextProvider,
67             SpringDocConfigProperties springDocConfigProperties,
68             Optional<List<OpenApiCustomiser>> openApiCustomisers,
69             Optional<SecurityOAuth2Provider> springSecurityOAuth2Provider) {
70         return new OpenApiResource(DEFAULT_GROUP_NAME, openAPIBuilder, requestBuilder,
71                 responseBuilder, operationParser,
72                 requestMappingHandlerMapping, servletContextProvider,
73                 openApiCustomisers, springDocConfigProperties, springSecurityOAuth2Provider);
74     }
75
76     @Bean
77     @ConditionalOnMissingBean
78     RequestBuilder requestBuilder(GenericParameterBuilder parameterBuilder, RequestBodyBuilder requestBodyBuilder,
79             OperationBuilder operationBuilder, Optional<List<OperationCustomizer>> operationCustomizers,
80             Optional<List<ParameterCustomizer>> parameterCustomizers,
81             LocalVariableTableParameterNameDiscoverer localSpringDocParameterNameDiscoverer) {
82         return new RequestBuilder(parameterBuilder, requestBodyBuilder,
83                 operationBuilder, operationCustomizers, parameterCustomizers, localSpringDocParameterNameDiscoverer);
84     }
85
86     @Bean
87     @ConditionalOnMissingBean
88     GenericResponseBuilder responseBuilder(OperationBuilder operationBuilder, List<ReturnTypeParser> returnTypeParsers, SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils) {
89         return new GenericResponseBuilder(operationBuilder, returnTypeParsers, springDocConfigProperties, propertyResolverUtils);
90     }
91
92     @ConditionalOnProperty(SPRINGDOC_SHOW_ACTUATOR)
93     @ConditionalOnClass(WebMvcEndpointHandlerMapping.class)
94     class SpringDocWebMvcActuatorConfiguration {
95
96         @Bean
97         @ConditionalOnMissingBean
98         ActuatorProvider actuatorProvider(WebMvcEndpointHandlerMapping webMvcEndpointHandlerMapping) {
99             return new ActuatorProvider(webMvcEndpointHandlerMapping);
100         }
101
102         @Bean
103         OperationCustomizer actuatorCustomizer(ActuatorProvider actuatorProvider) {
104             return new OperationCustomizer() {
105                 private int methodCount;
106
107                 @Override
108                 public Operation customize(Operation operation, HandlerMethod handlerMethod) {
109                     if (operation.getTags() != null && operation.getTags().contains(actuatorProvider.getTag().getName())) {
110                         operation.setSummary(handlerMethod.toString());
111                         operation.setOperationId(operation.getOperationId() + "_" + methodCount++);
112                     }
113                     return operation;
114                 }
115             };
116         }
117
118     }
119 }
120