001/* 002 * Copyright 2002-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 * 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.jmx.export.assembler; 018 019import java.lang.reflect.Method; 020import java.util.Arrays; 021import java.util.Enumeration; 022import java.util.HashMap; 023import java.util.HashSet; 024import java.util.Map; 025import java.util.Properties; 026import java.util.Set; 027 028import org.springframework.lang.Nullable; 029import org.springframework.util.StringUtils; 030 031/** 032 * Subclass of {@code AbstractReflectiveMBeanInfoAssembler} that allows 033 * to specify method names to be exposed as MBean operations and attributes. 034 * JavaBean getters and setters will automatically be exposed as JMX attributes. 035 * 036 * <p>You can supply an array of method names via the {@code managedMethods} 037 * property. If you have multiple beans and you wish each bean to use a different 038 * set of method names, then you can map bean keys (that is the name used to pass 039 * the bean to the {@code MBeanExporter}) to a list of method names using the 040 * {@code methodMappings} property. 041 * 042 * <p>If you specify values for both {@code methodMappings} and 043 * {@code managedMethods}, Spring will attempt to find method names in the 044 * mappings first. If no method names for the bean are found, it will use the 045 * method names defined by {@code managedMethods}. 046 * 047 * @author Juergen Hoeller 048 * @since 1.2 049 * @see #setManagedMethods 050 * @see #setMethodMappings 051 * @see InterfaceBasedMBeanInfoAssembler 052 * @see SimpleReflectiveMBeanInfoAssembler 053 * @see MethodExclusionMBeanInfoAssembler 054 * @see org.springframework.jmx.export.MBeanExporter 055 */ 056public class MethodNameBasedMBeanInfoAssembler extends AbstractConfigurableMBeanInfoAssembler { 057 058 /** 059 * Stores the set of method names to use for creating the management interface. 060 */ 061 @Nullable 062 private Set<String> managedMethods; 063 064 /** 065 * Stores the mappings of bean keys to an array of method names. 066 */ 067 @Nullable 068 private Map<String, Set<String>> methodMappings; 069 070 071 /** 072 * Set the array of method names to use for creating the management info. 073 * These method names will be used for a bean if no entry corresponding to 074 * that bean is found in the {@code methodMappings} property. 075 * @param methodNames an array of method names indicating the methods to use 076 * @see #setMethodMappings 077 */ 078 public void setManagedMethods(String... methodNames) { 079 this.managedMethods = new HashSet<>(Arrays.asList(methodNames)); 080 } 081 082 /** 083 * Set the mappings of bean keys to a comma-separated list of method names. 084 * The property key should match the bean key and the property value should match 085 * the list of method names. When searching for method names for a bean, Spring 086 * will check these mappings first. 087 * @param mappings the mappings of bean keys to method names 088 */ 089 public void setMethodMappings(Properties mappings) { 090 this.methodMappings = new HashMap<>(); 091 for (Enumeration<?> en = mappings.keys(); en.hasMoreElements();) { 092 String beanKey = (String) en.nextElement(); 093 String[] methodNames = StringUtils.commaDelimitedListToStringArray(mappings.getProperty(beanKey)); 094 this.methodMappings.put(beanKey, new HashSet<>(Arrays.asList(methodNames))); 095 } 096 } 097 098 099 @Override 100 protected boolean includeReadAttribute(Method method, String beanKey) { 101 return isMatch(method, beanKey); 102 } 103 104 @Override 105 protected boolean includeWriteAttribute(Method method, String beanKey) { 106 return isMatch(method, beanKey); 107 } 108 109 @Override 110 protected boolean includeOperation(Method method, String beanKey) { 111 return isMatch(method, beanKey); 112 } 113 114 protected boolean isMatch(Method method, String beanKey) { 115 if (this.methodMappings != null) { 116 Set<String> methodNames = this.methodMappings.get(beanKey); 117 if (methodNames != null) { 118 return methodNames.contains(method.getName()); 119 } 120 } 121 return (this.managedMethods != null && this.managedMethods.contains(method.getName())); 122 } 123 124}