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}