001/* 002 * Copyright 2021 Anyware Services 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 */ 016package org.ametys.core.mbean; 017 018import javax.management.Attribute; 019import javax.management.AttributeList; 020import javax.management.AttributeNotFoundException; 021import javax.management.DynamicMBean; 022import javax.management.InvalidAttributeValueException; 023import javax.management.MBeanAttributeInfo; 024import javax.management.MBeanConstructorInfo; 025import javax.management.MBeanException; 026import javax.management.MBeanInfo; 027import javax.management.MBeanNotificationInfo; 028import javax.management.MBeanOperationInfo; 029import javax.management.ReflectionException; 030import javax.management.RuntimeOperationsException; 031 032import org.ametys.runtime.plugin.component.AbstractLogEnabled; 033 034/** 035 * Abstract class for Ametys Dynamic MBean. 036 */ 037public abstract class AbstractAmetysDynamicMBean extends AbstractLogEnabled implements DynamicMBean 038{ 039 /** The MBean metadata */ 040 protected MBeanInfo _mBeanInfo; 041 042 /** 043 * AbstractAmetysDynamicMBean basic constructor. 044 * Generate the MBean info. 045 */ 046 public AbstractAmetysDynamicMBean() 047 { 048 buildDynamicMBeanInfo(); 049 } 050 051 @Override 052 public Object getAttribute(String attributeName) throws AttributeNotFoundException 053 { 054 // Check attribute_name to avoid NullPointerException later on 055 if (attributeName == null) 056 { 057 throw new RuntimeOperationsException( 058 new IllegalArgumentException("Attribute name cannot be null"), 059 "Cannot invoke a getter of " + this.getClass().getName() + " with null attribute name"); 060 } 061 062 Object attribute = _getAttribute(attributeName); 063 064 // If attribute_name has not been recognized 065 if (attribute == null) 066 { 067 throw new AttributeNotFoundException("Cannot find " + attributeName + " attribute in " + this.getClass().getName()); 068 } 069 return attribute; 070 } 071 072 /** 073 * Get the value of the attribute. 074 * This method should assume that attributeName is not null. 075 * And return null if the name is not recognized 076 * @param attributeName the name of the attribute 077 * @return the value of the attribute 078 */ 079 protected abstract Object _getAttribute(String attributeName); 080 081 @Override 082 public AttributeList getAttributes(String[] attributeNames) 083 { 084 // Check attributeNames to avoid NullPointerException later on 085 if (attributeNames == null) 086 { 087 throw new RuntimeOperationsException( 088 new IllegalArgumentException( 089 "attributeNames[] cannot be null"), 090 "Cannot invoke a getter of " + this.getClass().getName()); 091 } 092 AttributeList resultList = new AttributeList(); 093 094 // if attributeNames is empty, return an empty result list 095 if (attributeNames.length == 0) 096 { 097 return resultList; 098 } 099 100 // build the result attribute list 101 for (int i = 0; i < attributeNames.length; i++) 102 { 103 try 104 { 105 Object value = getAttribute(attributeNames[i]); 106 resultList.add(new Attribute(attributeNames[i], value)); 107 } 108 catch (Exception e) 109 { 110 getLogger().error("Failed to get attribute {}", attributeNames[i], e); 111 } 112 } 113 return resultList; 114 } 115 116 @Override 117 public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException 118 { 119 // we don't implement any method to invoke so no need 120 throw new UnsupportedOperationException("No invoke method defined for this MBean."); 121 } 122 123 @Override 124 public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException 125 { 126 // we don't need to set any attribute 127 throw new UnsupportedOperationException("Method to set attribute is not defined for this MBean."); 128 } 129 130 @Override 131 public AttributeList setAttributes(AttributeList attributes) 132 { 133 // we don't need to set any attribute 134 throw new UnsupportedOperationException("Method to set attributes is not defined for this MBean."); 135 } 136 137 @Override 138 public MBeanInfo getMBeanInfo() 139 { 140 return _mBeanInfo; 141 } 142 143 144 private void buildDynamicMBeanInfo() 145 { 146 _mBeanInfo = new MBeanInfo(getMBeanName(), 147 getMBeanDescription(), 148 getMBeanAttributes(), 149 getMBeanConstructorInfo(), 150 getMBeanOperationInfo(), 151 getMBeanNotificationInfo()); 152 } 153 154 /** 155 * Get the human readable name of the MBean. 156 * This name will be exposed. 157 * @return the name 158 */ 159 protected abstract String getMBeanName(); 160 161 /** 162 * Get the description of the MBean 163 * @return the description 164 */ 165 protected abstract String getMBeanDescription(); 166 167 /** 168 * Get the definition of the attributes exposed by the MBean. 169 * @return the attributes information 170 */ 171 protected abstract MBeanAttributeInfo[] getMBeanAttributes(); 172 173 /** 174 * Get the definition of the constructors exposed by the MBean. 175 * @return the constructors information 176 */ 177 protected MBeanConstructorInfo[] getMBeanConstructorInfo() 178 { 179 // We usually don't set any constructor 180 return new MBeanConstructorInfo[0]; 181 } 182 183 /** 184 * Get the definition of the operation methods exposed by the MBean 185 * @return the operations information 186 */ 187 protected MBeanOperationInfo[] getMBeanOperationInfo() 188 { 189 // We usually don't set any operation 190 return new MBeanOperationInfo[0]; 191 } 192 193 /** 194 * Get the definition of the notification exposed by the MBean 195 * @return the notification information 196 */ 197 protected MBeanNotificationInfo[] getMBeanNotificationInfo() 198 { 199 // We usually don't set any notification 200 return new MBeanNotificationInfo[0]; 201 } 202 203 /** 204 * render a human readable filesize 205 * @param size the size in byte 206 * @return the human readable string 207 */ 208 protected String _fileSize(long size) 209 { 210 final long byteLimit = 1024; 211 final long kbLimit = 1048576; 212 final long mbLimit = 1073741824; 213 String fileSize; 214 if (size < byteLimit) 215 { 216 if (size == 1) 217 { 218 fileSize = "1 byte"; 219 } 220 else 221 { 222 fileSize = String.format("%d bytes", size); 223 } 224 } 225 else if (size < kbLimit) 226 { 227 fileSize = String.format("%.2f KB", ((double) size) / byteLimit); 228 } 229 else if (size < mbLimit) 230 { 231 fileSize = String.format("%.2f MB", ((double) size) / kbLimit); 232 } 233 else 234 { 235 fileSize = String.format("%.2f GB", ((double) size) / mbLimit); 236 } 237 238 return fileSize; 239 } 240}