001/* 002 * Copyright 2002-2017 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 * {@code AbstractReflectiveMBeanInfoAssembler} subclass that allows 033 * method names to be explicitly excluded as MBean operations and attributes. 034 * 035 * <p>Any method not explicitly excluded from the management interface will be exposed to 036 * JMX. JavaBean getters and setters will automatically be exposed as JMX attributes. 037 * 038 * <p>You can supply an array of method names via the {@code ignoredMethods} 039 * property. If you have multiple beans and you wish each bean to use a different 040 * set of method names, then you can map bean keys (that is the name used to pass 041 * the bean to the {@code MBeanExporter}) to a list of method names using the 042 * {@code ignoredMethodMappings} property. 043 * 044 * <p>If you specify values for both {@code ignoredMethodMappings} and 045 * {@code ignoredMethods}, Spring will attempt to find method names in the 046 * mappings first. If no method names for the bean are found, it will use the 047 * method names defined by {@code ignoredMethods}. 048 * 049 * @author Rob Harrop 050 * @author Seth Ladd 051 * @since 1.2.5 052 * @see #setIgnoredMethods 053 * @see #setIgnoredMethodMappings 054 * @see InterfaceBasedMBeanInfoAssembler 055 * @see SimpleReflectiveMBeanInfoAssembler 056 * @see MethodNameBasedMBeanInfoAssembler 057 * @see org.springframework.jmx.export.MBeanExporter 058 */ 059public class MethodExclusionMBeanInfoAssembler extends AbstractConfigurableMBeanInfoAssembler { 060 061 @Nullable 062 private Set<String> ignoredMethods; 063 064 @Nullable 065 private Map<String, Set<String>> ignoredMethodMappings; 066 067 068 /** 069 * Set the array of method names to be <b>ignored</b> when creating the management info. 070 * <p>These method names will be used for a bean if no entry corresponding to 071 * that bean is found in the {@code ignoredMethodsMappings} property. 072 * @see #setIgnoredMethodMappings(java.util.Properties) 073 */ 074 public void setIgnoredMethods(String... ignoredMethodNames) { 075 this.ignoredMethods = new HashSet<>(Arrays.asList(ignoredMethodNames)); 076 } 077 078 /** 079 * Set the mappings of bean keys to a comma-separated list of method names. 080 * <p>These method names are <b>ignored</b> when creating the management interface. 081 * <p>The property key must match the bean key and the property value must match 082 * the list of method names. When searching for method names to ignore for a bean, 083 * Spring will check these mappings first. 084 */ 085 public void setIgnoredMethodMappings(Properties mappings) { 086 this.ignoredMethodMappings = new HashMap<>(); 087 for (Enumeration<?> en = mappings.keys(); en.hasMoreElements();) { 088 String beanKey = (String) en.nextElement(); 089 String[] methodNames = StringUtils.commaDelimitedListToStringArray(mappings.getProperty(beanKey)); 090 this.ignoredMethodMappings.put(beanKey, new HashSet<>(Arrays.asList(methodNames))); 091 } 092 } 093 094 095 @Override 096 protected boolean includeReadAttribute(Method method, String beanKey) { 097 return isNotIgnored(method, beanKey); 098 } 099 100 @Override 101 protected boolean includeWriteAttribute(Method method, String beanKey) { 102 return isNotIgnored(method, beanKey); 103 } 104 105 @Override 106 protected boolean includeOperation(Method method, String beanKey) { 107 return isNotIgnored(method, beanKey); 108 } 109 110 /** 111 * Determine whether the given method is supposed to be included, 112 * that is, not configured as to be ignored. 113 * @param method the operation method 114 * @param beanKey the key associated with the MBean in the beans map 115 * of the {@code MBeanExporter} 116 */ 117 protected boolean isNotIgnored(Method method, String beanKey) { 118 if (this.ignoredMethodMappings != null) { 119 Set<String> methodNames = this.ignoredMethodMappings.get(beanKey); 120 if (methodNames != null) { 121 return !methodNames.contains(method.getName()); 122 } 123 } 124 if (this.ignoredMethods != null) { 125 return !this.ignoredMethods.contains(method.getName()); 126 } 127 return true; 128 } 129 130}