001/*
002 * Copyright 2002-2020 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 *      https://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.context.annotation;
018
019import java.util.Map;
020import javax.management.MBeanServer;
021import javax.naming.NamingException;
022
023import org.springframework.beans.factory.BeanFactory;
024import org.springframework.beans.factory.BeanFactoryAware;
025import org.springframework.beans.factory.config.BeanDefinition;
026import org.springframework.context.EnvironmentAware;
027import org.springframework.core.annotation.AnnotationAttributes;
028import org.springframework.core.env.Environment;
029import org.springframework.core.type.AnnotationMetadata;
030import org.springframework.jmx.MBeanServerNotFoundException;
031import org.springframework.jmx.export.annotation.AnnotationMBeanExporter;
032import org.springframework.jmx.support.RegistrationPolicy;
033import org.springframework.jmx.support.WebSphereMBeanServerFactoryBean;
034import org.springframework.jndi.JndiLocatorDelegate;
035import org.springframework.util.ClassUtils;
036import org.springframework.util.StringUtils;
037
038/**
039 * {@code @Configuration} class that registers a {@link AnnotationMBeanExporter} bean.
040 *
041 * <p>This configuration class is automatically imported when using the
042 * {@link EnableMBeanExport} annotation. See its javadoc for complete usage details.
043 *
044 * @author Phillip Webb
045 * @author Chris Beams
046 * @since 3.2
047 * @see EnableMBeanExport
048 */
049@Configuration
050@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
051public class MBeanExportConfiguration implements ImportAware, EnvironmentAware, BeanFactoryAware {
052
053        private static final String MBEAN_EXPORTER_BEAN_NAME = "mbeanExporter";
054
055        private AnnotationAttributes enableMBeanExport;
056
057        private Environment environment;
058
059        private BeanFactory beanFactory;
060
061
062        @Override
063        public void setImportMetadata(AnnotationMetadata importMetadata) {
064                Map<String, Object> map = importMetadata.getAnnotationAttributes(EnableMBeanExport.class.getName());
065                this.enableMBeanExport = AnnotationAttributes.fromMap(map);
066                if (this.enableMBeanExport == null) {
067                        throw new IllegalArgumentException(
068                                        "@EnableMBeanExport is not present on importing class " + importMetadata.getClassName());
069                }
070        }
071
072        @Override
073        public void setEnvironment(Environment environment) {
074                this.environment = environment;
075        }
076
077        @Override
078        public void setBeanFactory(BeanFactory beanFactory) {
079                this.beanFactory = beanFactory;
080        }
081
082
083        @Bean(name = MBEAN_EXPORTER_BEAN_NAME)
084        @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
085        public AnnotationMBeanExporter mbeanExporter() {
086                AnnotationMBeanExporter exporter = new AnnotationMBeanExporter();
087                setupDomain(exporter);
088                setupServer(exporter);
089                setupRegistrationPolicy(exporter);
090                return exporter;
091        }
092
093        private void setupDomain(AnnotationMBeanExporter exporter) {
094                String defaultDomain = this.enableMBeanExport.getString("defaultDomain");
095                if (defaultDomain != null && this.environment != null) {
096                        defaultDomain = this.environment.resolvePlaceholders(defaultDomain);
097                }
098                if (StringUtils.hasText(defaultDomain)) {
099                        exporter.setDefaultDomain(defaultDomain);
100                }
101        }
102
103        private void setupServer(AnnotationMBeanExporter exporter) {
104                String server = this.enableMBeanExport.getString("server");
105                if (server != null && this.environment != null) {
106                        server = this.environment.resolvePlaceholders(server);
107                }
108                if (StringUtils.hasText(server)) {
109                        exporter.setServer(this.beanFactory.getBean(server, MBeanServer.class));
110                }
111                else {
112                        SpecificPlatform specificPlatform = SpecificPlatform.get();
113                        if (specificPlatform != null) {
114                                exporter.setServer(specificPlatform.getMBeanServer());
115                        }
116                }
117        }
118
119        private void setupRegistrationPolicy(AnnotationMBeanExporter exporter) {
120                RegistrationPolicy registrationPolicy = this.enableMBeanExport.getEnum("registration");
121                exporter.setRegistrationPolicy(registrationPolicy);
122        }
123
124
125        public enum SpecificPlatform {
126
127                WEBLOGIC("weblogic.management.Helper") {
128                        @Override
129                        public MBeanServer getMBeanServer() {
130                                try {
131                                        return new JndiLocatorDelegate().lookup("java:comp/env/jmx/runtime", MBeanServer.class);
132                                }
133                                catch (NamingException ex) {
134                                        throw new MBeanServerNotFoundException("Failed to retrieve WebLogic MBeanServer from JNDI", ex);
135                                }
136                        }
137                },
138
139                WEBSPHERE("com.ibm.websphere.management.AdminServiceFactory") {
140                        @Override
141                        public MBeanServer getMBeanServer() {
142                                WebSphereMBeanServerFactoryBean fb = new WebSphereMBeanServerFactoryBean();
143                                fb.afterPropertiesSet();
144                                return fb.getObject();
145                        }
146                };
147
148                private final String identifyingClass;
149
150                SpecificPlatform(String identifyingClass) {
151                        this.identifyingClass = identifyingClass;
152                }
153
154                public abstract MBeanServer getMBeanServer();
155
156                public static SpecificPlatform get() {
157                        ClassLoader classLoader = MBeanExportConfiguration.class.getClassLoader();
158                        for (SpecificPlatform environment : values()) {
159                                if (ClassUtils.isPresent(environment.identifyingClass, classLoader)) {
160                                        return environment;
161                                }
162                        }
163                        return null;
164                }
165        }
166
167}