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.admin; 018 019import java.lang.management.ManagementFactory; 020 021import javax.management.MBeanServer; 022import javax.management.MalformedObjectNameException; 023import javax.management.ObjectName; 024 025import org.apache.commons.logging.Log; 026import org.apache.commons.logging.LogFactory; 027 028import org.springframework.beans.BeansException; 029import org.springframework.beans.factory.DisposableBean; 030import org.springframework.beans.factory.InitializingBean; 031import org.springframework.boot.context.event.ApplicationReadyEvent; 032import org.springframework.boot.web.context.WebServerInitializedEvent; 033import org.springframework.context.ApplicationContext; 034import org.springframework.context.ApplicationContextAware; 035import org.springframework.context.ApplicationEvent; 036import org.springframework.context.ConfigurableApplicationContext; 037import org.springframework.context.EnvironmentAware; 038import org.springframework.context.event.GenericApplicationListener; 039import org.springframework.core.Ordered; 040import org.springframework.core.ResolvableType; 041import org.springframework.core.env.Environment; 042import org.springframework.core.env.StandardEnvironment; 043import org.springframework.lang.Nullable; 044import org.springframework.util.Assert; 045 046/** 047 * Register a {@link SpringApplicationAdminMXBean} implementation to the platform 048 * {@link MBeanServer}. 049 * 050 * @author Stephane Nicoll 051 * @author Andy Wilkinson 052 * @since 1.3.0 053 */ 054public class SpringApplicationAdminMXBeanRegistrar implements ApplicationContextAware, 055 GenericApplicationListener, EnvironmentAware, InitializingBean, DisposableBean { 056 057 private static final Log logger = LogFactory.getLog(SpringApplicationAdmin.class); 058 059 private ConfigurableApplicationContext applicationContext; 060 061 private Environment environment = new StandardEnvironment(); 062 063 private final ObjectName objectName; 064 065 private boolean ready = false; 066 067 private boolean embeddedWebApplication = false; 068 069 public SpringApplicationAdminMXBeanRegistrar(String name) 070 throws MalformedObjectNameException { 071 this.objectName = new ObjectName(name); 072 } 073 074 @Override 075 public void setApplicationContext(ApplicationContext applicationContext) 076 throws BeansException { 077 Assert.state(applicationContext instanceof ConfigurableApplicationContext, 078 "ApplicationContext does not implement ConfigurableApplicationContext"); 079 this.applicationContext = (ConfigurableApplicationContext) applicationContext; 080 } 081 082 @Override 083 public void setEnvironment(Environment environment) { 084 this.environment = environment; 085 } 086 087 @Override 088 public boolean supportsEventType(ResolvableType eventType) { 089 Class<?> type = eventType.getRawClass(); 090 if (type == null) { 091 return false; 092 } 093 return ApplicationReadyEvent.class.isAssignableFrom(type) 094 || WebServerInitializedEvent.class.isAssignableFrom(type); 095 } 096 097 @Override 098 public boolean supportsSourceType(@Nullable Class<?> sourceType) { 099 return true; 100 } 101 102 @Override 103 public void onApplicationEvent(ApplicationEvent event) { 104 if (event instanceof ApplicationReadyEvent) { 105 onApplicationReadyEvent((ApplicationReadyEvent) event); 106 } 107 if (event instanceof WebServerInitializedEvent) { 108 onWebServerInitializedEvent((WebServerInitializedEvent) event); 109 } 110 } 111 112 @Override 113 public int getOrder() { 114 return Ordered.HIGHEST_PRECEDENCE; 115 } 116 117 void onApplicationReadyEvent(ApplicationReadyEvent event) { 118 if (this.applicationContext.equals(event.getApplicationContext())) { 119 this.ready = true; 120 } 121 } 122 123 void onWebServerInitializedEvent(WebServerInitializedEvent event) { 124 if (this.applicationContext.equals(event.getApplicationContext())) { 125 this.embeddedWebApplication = true; 126 } 127 } 128 129 @Override 130 public void afterPropertiesSet() throws Exception { 131 MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 132 server.registerMBean(new SpringApplicationAdmin(), this.objectName); 133 if (logger.isDebugEnabled()) { 134 logger.debug("Application Admin MBean registered with name '" 135 + this.objectName + "'"); 136 } 137 } 138 139 @Override 140 public void destroy() throws Exception { 141 ManagementFactory.getPlatformMBeanServer().unregisterMBean(this.objectName); 142 } 143 144 private class SpringApplicationAdmin implements SpringApplicationAdminMXBean { 145 146 @Override 147 public boolean isReady() { 148 return SpringApplicationAdminMXBeanRegistrar.this.ready; 149 } 150 151 @Override 152 public boolean isEmbeddedWebApplication() { 153 return SpringApplicationAdminMXBeanRegistrar.this.embeddedWebApplication; 154 } 155 156 @Override 157 public String getProperty(String key) { 158 return SpringApplicationAdminMXBeanRegistrar.this.environment 159 .getProperty(key); 160 } 161 162 @Override 163 public void shutdown() { 164 logger.info("Application shutdown requested."); 165 SpringApplicationAdminMXBeanRegistrar.this.applicationContext.close(); 166 } 167 168 } 169 170}