001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.actuate.autoconfigure.cloudfoundry;
018
019import java.util.Collection;
020import java.util.List;
021
022import org.springframework.boot.actuate.endpoint.EndpointFilter;
023import org.springframework.boot.actuate.endpoint.invoke.OperationInvokerAdvisor;
024import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
025import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
026import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
027import org.springframework.boot.actuate.endpoint.web.PathMapper;
028import org.springframework.boot.actuate.endpoint.web.annotation.EndpointWebExtension;
029import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
030import org.springframework.boot.actuate.health.HealthEndpoint;
031import org.springframework.context.ApplicationContext;
032import org.springframework.core.annotation.AnnotatedElementUtils;
033import org.springframework.core.annotation.AnnotationAttributes;
034
035/**
036 * {@link WebEndpointDiscoverer} for Cloud Foundry that uses Cloud Foundry specific
037 * extensions for the {@link HealthEndpoint}.
038 *
039 * @author Madhura Bhave
040 * @since 2.0.0
041 */
042public class CloudFoundryWebEndpointDiscoverer extends WebEndpointDiscoverer {
043
044        /**
045         * Create a new {@link WebEndpointDiscoverer} instance.
046         * @param applicationContext the source application context
047         * @param parameterValueMapper the parameter value mapper
048         * @param endpointMediaTypes the endpoint media types
049         * @param endpointPathMappers the endpoint path mappers
050         * @param invokerAdvisors invoker advisors to apply
051         * @param filters filters to apply
052         */
053        public CloudFoundryWebEndpointDiscoverer(ApplicationContext applicationContext,
054                        ParameterValueMapper parameterValueMapper,
055                        EndpointMediaTypes endpointMediaTypes, List<PathMapper> endpointPathMappers,
056                        Collection<OperationInvokerAdvisor> invokerAdvisors,
057                        Collection<EndpointFilter<ExposableWebEndpoint>> filters) {
058                super(applicationContext, parameterValueMapper, endpointMediaTypes,
059                                endpointPathMappers, invokerAdvisors, filters);
060        }
061
062        @Override
063        protected boolean isExtensionExposed(Object extensionBean) {
064                if (isHealthEndpointExtension(extensionBean)
065                                && !isCloudFoundryHealthEndpointExtension(extensionBean)) {
066                        // Filter regular health endpoint extensions so a CF version can replace them
067                        return false;
068                }
069                return true;
070        }
071
072        private boolean isHealthEndpointExtension(Object extensionBean) {
073                AnnotationAttributes attributes = AnnotatedElementUtils
074                                .getMergedAnnotationAttributes(extensionBean.getClass(),
075                                                EndpointWebExtension.class);
076                Class<?> endpoint = (attributes != null) ? attributes.getClass("endpoint") : null;
077                return (endpoint != null && HealthEndpoint.class.isAssignableFrom(endpoint));
078        }
079
080        private boolean isCloudFoundryHealthEndpointExtension(Object extensionBean) {
081                return AnnotatedElementUtils.hasAnnotation(extensionBean.getClass(),
082                                HealthEndpointCloudFoundryExtension.class);
083        }
084
085}