Source for gnu.java.lang.management.BeanImpl

   1: /* BeanImpl.java - A common superclass for bean implementations.
   2:    Copyright (C) 2006 Free Software Foundation
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.java.lang.management;
  39: 
  40: import gnu.javax.management.Translator;
  41: 
  42: import java.lang.management.ManagementPermission;
  43: 
  44: import java.lang.reflect.Array;
  45: import java.lang.reflect.Method;
  46: import java.lang.reflect.InvocationTargetException;
  47: import java.lang.reflect.TypeVariable;
  48: 
  49: import java.util.ArrayList;
  50: import java.util.Iterator;
  51: import java.util.List;
  52: import java.util.Map;
  53: import java.util.Set;
  54: 
  55: import javax.management.AttributeNotFoundException;
  56: import javax.management.MBeanAttributeInfo;
  57: import javax.management.MBeanConstructorInfo;
  58: import javax.management.MBeanException;
  59: import javax.management.MBeanInfo;
  60: import javax.management.MBeanOperationInfo;
  61: import javax.management.MBeanParameterInfo;
  62: import javax.management.MBeanInfo;
  63: import javax.management.NotCompliantMBeanException;
  64: import javax.management.ReflectionException;
  65: import javax.management.StandardMBean;
  66: 
  67: import javax.management.openmbean.ArrayType;
  68: import javax.management.openmbean.CompositeData;
  69: import javax.management.openmbean.CompositeDataSupport;
  70: import javax.management.openmbean.CompositeType;
  71: import javax.management.openmbean.OpenDataException;
  72: import javax.management.openmbean.OpenMBeanAttributeInfo;
  73: import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
  74: import javax.management.openmbean.OpenMBeanConstructorInfo;
  75: import javax.management.openmbean.OpenMBeanConstructorInfoSupport;
  76: import javax.management.openmbean.OpenMBeanInfo;
  77: import javax.management.openmbean.OpenMBeanInfoSupport;
  78: import javax.management.openmbean.OpenMBeanOperationInfo;
  79: import javax.management.openmbean.OpenMBeanOperationInfoSupport;
  80: import javax.management.openmbean.OpenMBeanParameterInfo;
  81: import javax.management.openmbean.OpenMBeanParameterInfoSupport;
  82: import javax.management.openmbean.OpenType;
  83: import javax.management.openmbean.SimpleType;
  84: import javax.management.openmbean.TabularData;
  85: import javax.management.openmbean.TabularDataSupport;
  86: import javax.management.openmbean.TabularType;
  87: 
  88: /**
  89:  * A common superclass for bean implementations.
  90:  *
  91:  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
  92:  * @since 1.5
  93:  */
  94: public class BeanImpl
  95:   extends StandardMBean
  96: {
  97: 
  98:   /**
  99:    * Cached open bean information.
 100:    */
 101:   private OpenMBeanInfo openInfo;
 102: 
 103:   /**
 104:    * Constructs a new <code>BeanImpl</code>.
 105:    *
 106:    * @param iface the bean interface being implemented.
 107:    * @throws NotCompliantMBeanException if this class doesn't implement
 108:    *                                    the interface or a method appears
 109:    *                                    in the interface that doesn't comply
 110:    *                                    with the naming conventions.
 111:    */
 112:   protected BeanImpl(Class iface)
 113:     throws NotCompliantMBeanException
 114:   {
 115:     super(iface);
 116:   }
 117: 
 118:   protected void cacheMBeanInfo(MBeanInfo info)
 119:   {
 120:     if (info == null)
 121:       return;
 122:     try
 123:       {
 124:     MBeanAttributeInfo[] oldA = info.getAttributes();
 125:     OpenMBeanAttributeInfo[] attribs =
 126:       new OpenMBeanAttributeInfoSupport[oldA.length];
 127:     for (int a = 0; a < oldA.length; ++a)
 128:       {
 129:         OpenMBeanParameterInfo param = Translator.translate(oldA[a].getType());
 130:         if (param.getMinValue() == null)
 131:           {
 132:         Object[] lv;
 133:         if (param.getLegalValues() == null)
 134:           lv = null;
 135:         else
 136:           lv = param.getLegalValues().toArray();
 137:         attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(),
 138:                                    oldA[a].getDescription(),
 139:                                    ((OpenType<Object>)
 140:                                 param.getOpenType()),
 141:                                    oldA[a].isReadable(),
 142:                                    oldA[a].isWritable(),
 143:                                    oldA[a].isIs(),
 144:                                    param.getDefaultValue(),
 145:                                    lv);
 146:           }
 147:         else
 148:           attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(),
 149:                                  oldA[a].getDescription(),
 150:                                  ((OpenType<Object>)
 151:                                   param.getOpenType()),
 152:                                  oldA[a].isReadable(),
 153:                                  oldA[a].isWritable(),
 154:                                  oldA[a].isIs(),
 155:                                  param.getDefaultValue(),
 156:                                  ((Comparable<Object>)
 157:                                    param.getMinValue()),
 158:                                  ((Comparable<Object>)
 159:                                    param.getMaxValue()));
 160:       }
 161:     MBeanConstructorInfo[] oldC = info.getConstructors();
 162:     OpenMBeanConstructorInfo[] cons = new OpenMBeanConstructorInfoSupport[oldC.length];
 163:     for (int a = 0; a < oldC.length; ++a)
 164:       cons[a] =
 165:         new OpenMBeanConstructorInfoSupport(oldC[a].getName(),
 166:                         oldC[a].getDescription(),
 167:                         translateSignature(oldC[a].getSignature()));
 168:     MBeanOperationInfo[] oldO = info.getOperations();
 169:     OpenMBeanOperationInfo[] ops = new OpenMBeanOperationInfoSupport[oldO.length];
 170:     for (int a = 0; a < oldO.length; ++a)
 171:       ops[a] =
 172:     new OpenMBeanOperationInfoSupport(oldO[a].getName(),
 173:                       oldO[a].getDescription(),
 174:                       translateSignature(oldO[a].getSignature()),
 175:                       Translator.translate(oldO[a].getReturnType()).getOpenType(),
 176:                       oldO[a].getImpact());
 177:     openInfo = new OpenMBeanInfoSupport(info.getClassName(), info.getDescription(),
 178:                         attribs, cons, ops, info.getNotifications());
 179:       }
 180:     catch (OpenDataException e)
 181:       {
 182:     throw (InternalError) (new InternalError("A problem occurred creating the open type " +
 183:                          "descriptors.").initCause(e));
 184:       }
 185:   }
 186: 
 187:   protected void checkMonitorPermissions()
 188:   {
 189:     SecurityManager sm = System.getSecurityManager();
 190:     if (sm != null)
 191:       sm.checkPermission(new ManagementPermission("monitor"));
 192:   }
 193: 
 194:   protected void checkControlPermissions()
 195:   {
 196:     SecurityManager sm = System.getSecurityManager();
 197:     if (sm != null)
 198:       sm.checkPermission(new ManagementPermission("control"));
 199:   }
 200: 
 201:   public Object getAttribute(String attribute)
 202:     throws AttributeNotFoundException, MBeanException,
 203:        ReflectionException
 204:   {
 205:     Object value = super.getAttribute(attribute);
 206:     if (value instanceof Enum)
 207:       return ((Enum) value).name();
 208:     Class vClass = value.getClass();
 209:     if (vClass.isArray())
 210:       vClass = vClass.getComponentType();
 211:     String cName = vClass.getName();
 212:     String[] allowedTypes = OpenType.ALLOWED_CLASSNAMES;
 213:     for (int a = 0; a < allowedTypes.length; ++a)
 214:       if (cName.equals(allowedTypes[a]))
 215:     return value;
 216:     OpenMBeanInfo info = (OpenMBeanInfo) getMBeanInfo();
 217:     MBeanAttributeInfo[] attribs =
 218:       (MBeanAttributeInfo[]) info.getAttributes();
 219:     OpenType type = null;
 220:     for (int a = 0; a < attribs.length; ++a)
 221:       if (attribs[a].getName().equals(attribute))
 222:     type = ((OpenMBeanAttributeInfo) attribs[a]).getOpenType();
 223:     if (value instanceof List)
 224:       {
 225:     try
 226:       {
 227:         Class e =
 228:           Class.forName(((ArrayType) type).getElementOpenType().getClassName());
 229:         List l = (List) value;
 230:         Object[] array = (Object[]) Array.newInstance(e, l.size());
 231:         return l.toArray(array);
 232:       }
 233:     catch (ClassNotFoundException e)
 234:       {
 235:         throw (InternalError) (new InternalError("The class of the list " +
 236:                              "element type could not " +
 237:                              "be created").initCause(e));
 238:       }
 239:       }
 240:     if (value instanceof Map)
 241:       {
 242:     TabularType ttype = (TabularType) type;
 243:     TabularData data = new TabularDataSupport(ttype);
 244:     Iterator it = ((Map) value).entrySet().iterator();
 245:     while (it.hasNext())
 246:       {
 247:         Map.Entry entry = (Map.Entry) it.next();
 248:         try 
 249:           {
 250:         data.put(new CompositeDataSupport(ttype.getRowType(),
 251:                           new String[] { 
 252:                             "key", 
 253:                             "value" 
 254:                           },
 255:                           new Object[] { 
 256:                             entry.getKey(),
 257:                             entry.getValue()
 258:                           }));
 259:           }
 260:         catch (OpenDataException e)
 261:           {
 262:         throw (InternalError) (new InternalError("A problem occurred " +
 263:                              "converting the map " +
 264:                              "to a composite data " +
 265:                              "structure.").initCause(e));
 266:           }
 267:       }
 268:     return data;
 269:       }
 270:     CompositeType cType = (CompositeType) type;
 271:     Set names = cType.keySet();
 272:     Iterator it = names.iterator();
 273:     List values = new ArrayList(names.size());
 274:     while (it.hasNext())
 275:       {
 276:     String field = (String) it.next();
 277:     Method getter = null;
 278:     try 
 279:       {
 280:         getter = vClass.getMethod("get" + field, null);
 281:       }
 282:     catch (NoSuchMethodException e)
 283:       {
 284:         /* Ignored; the type tells us it's there. */
 285:       }
 286:     try
 287:       {
 288:         values.add(getter.invoke(value, null));
 289:       }
 290:     catch (IllegalAccessException e)
 291:       {
 292:         throw new ReflectionException(e, "Failed to retrieve " + field);
 293:       }
 294:     catch (IllegalArgumentException e)
 295:       {
 296:         throw new ReflectionException(e, "Failed to retrieve " + field);
 297:       }
 298:     catch (InvocationTargetException e)
 299:       {
 300:         throw new MBeanException((Exception) e.getCause(),
 301:                      "The getter of " + field +
 302:                      " threw an exception");
 303:       }
 304:       }
 305:     try
 306:       {
 307:     return new CompositeDataSupport(cType, 
 308:                     (String[]) 
 309:                     names.toArray(new String[names.size()]),
 310:                     values.toArray());
 311:       }
 312:     catch (OpenDataException e)
 313:       {
 314:     throw (InternalError) (new InternalError("A problem occurred " +
 315:                          "converting the value " +
 316:                          "to a composite data " +
 317:                          "structure.").initCause(e));
 318:       }
 319:   }
 320:   
 321:   protected MBeanInfo getCachedMBeanInfo()
 322:   {
 323:     return (MBeanInfo) openInfo;
 324:   }
 325: 
 326:   public MBeanInfo getMBeanInfo()
 327:   {
 328:     super.getMBeanInfo();
 329:     return getCachedMBeanInfo();
 330:   }
 331: 
 332:   private OpenMBeanParameterInfo[] translateSignature(MBeanParameterInfo[] oldS)
 333:     throws OpenDataException
 334:   {
 335:     OpenMBeanParameterInfo[] sig = new OpenMBeanParameterInfoSupport[oldS.length];
 336:     for (int a = 0; a < oldS.length; ++a)
 337:       {
 338:     OpenMBeanParameterInfo param = Translator.translate(oldS[a].getType());
 339:     if (param.getMinValue() == null)
 340:       {
 341:         Object[] lv;
 342:         if (param.getLegalValues() == null)
 343:           lv = null;
 344:         else
 345:           lv = param.getLegalValues().toArray();
 346:         sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(),
 347:                                oldS[a].getDescription(),
 348:                                ((OpenType<Object>)
 349:                             param.getOpenType()),
 350:                                param.getDefaultValue(),
 351:                                lv);
 352:       }
 353:     else
 354:       sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(),
 355:                              oldS[a].getDescription(),
 356:                              ((OpenType<Object>)
 357:                               param.getOpenType()),
 358:                              param.getDefaultValue(),
 359:                              ((Comparable<Object>)
 360:                               param.getMinValue()),
 361:                              ((Comparable<Object>)
 362:                               param.getMaxValue()));
 363:       }
 364:     return sig;
 365:   }
 366: 
 367: 
 368: }