You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jl...@apache.org on 2004/03/18 11:04:50 UTC

cvs commit: incubator-geronimo/modules/kernel/src/test/org/apache/geronimo/gbean/jmx GBeanMBeanAttributeTest.java

jlaskowski    2004/03/18 02:04:50

  Modified:    modules/kernel/src/test/org/apache/geronimo/kernel
                        MockGBean.java
               modules/kernel/src/java/org/apache/geronimo/gbean
                        DynamicGAttributeInfo.java GBeanInfoFactory.java
               modules/kernel/src/java/org/apache/geronimo/gbean/jmx
                        GBeanMBeanAttribute.java
               modules/kernel/src/test/org/apache/geronimo/gbean/jmx
                        GBeanMBeanAttributeTest.java
  Added:       modules/kernel/src/test/org/apache/geronimo/kernel
                        MockDynamicGBean.java
  Log:
  Tests for GBeanMBeanAttribute and implied modifications
  
  Revision  Changes    Path
  1.15      +82 -1     incubator-geronimo/modules/kernel/src/test/org/apache/geronimo/kernel/MockGBean.java
  
  Index: MockGBean.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/kernel/src/test/org/apache/geronimo/kernel/MockGBean.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- MockGBean.java	13 Mar 2004 23:46:30 -0000	1.14
  +++ MockGBean.java	18 Mar 2004 10:04:50 -0000	1.15
  @@ -82,6 +82,87 @@
           return finalInt;
       }
   
  +    /**
  +     * Note the wrong return type, instead of int type.
  +     * 
  +     * @return
  +     */
  +    public String getAnotherFinalInt() {
  +        return null;
  +    }
  +
  +    /**
  +     * Parameter ignored
  +     * 
  +     * @param ignored
  +     */
  +    public void setAnotherFinalInt(int ignored) {
  +    }
  +
  +    /**
  +     * Only setter for YetAnotherFinalInt
  +     * 
  +     * @param ignored
  +     */
  +    public void setYetAnotherFinalInt(int ignored) {
  +    }
  +
  +    /**
  +     * @see #setYetAnotherFinalInt(int)
  +     */
  +    public void setCharAsYetAnotherFinalInt(char yetAnotherFinalInt) {
  +        setYetAnotherFinalInt((int) yetAnotherFinalInt);
  +    }
  +
  +    /**
  +     * @see #setYetAnotherFinalInt(int)
  +     */
  +    public void setBooleanAsYetAnotherFinalInt(boolean yetAnotherFinalInt) {
  +        setYetAnotherFinalInt((yetAnotherFinalInt ? 1 : 0));
  +    }
  +
  +    /**
  +     * @see #setYetAnotherFinalInt(int)
  +     */
  +    public void setByteAsYetAnotherFinalInt(byte yetAnotherFinalInt) {
  +        setYetAnotherFinalInt(yetAnotherFinalInt);
  +    }
  +
  +    /**
  +     * @see #setYetAnotherFinalInt(int)
  +     */
  +    public void setShortAsYetAnotherFinalInt(short yetAnotherFinalInt) {
  +        setYetAnotherFinalInt(yetAnotherFinalInt);
  +    }
  +
  +    /**
  +     * @see #setYetAnotherFinalInt(int)
  +     */
  +    public void setLongAsYetAnotherFinalInt(long yetAnotherFinalInt) {
  +        setYetAnotherFinalInt((int)yetAnotherFinalInt);
  +    }
  +
  +    /**
  +     * @see #setYetAnotherFinalInt(int)
  +     */
  +    public void setFloatAsYetAnotherFinalInt(float yetAnotherFinalInt) {
  +        setYetAnotherFinalInt((int)yetAnotherFinalInt);
  +    }
  +
  +    /**
  +     * @see #setYetAnotherFinalInt(int)
  +     */
  +    public void setDoubleAsYetAnotherFinalInt(double yetAnotherFinalInt) {
  +        setYetAnotherFinalInt((int)yetAnotherFinalInt);
  +    }
  +
  +    /**
  +     * Getter that returns nothing
  +     *  
  +     */
  +    public void getVoidGetterOfFinalInt() {
  +    }
  +
       public int getMutableInt() {
           return mutableInt;
       }
  
  
  
  1.1                  incubator-geronimo/modules/kernel/src/test/org/apache/geronimo/kernel/MockDynamicGBean.java
  
  Index: MockDynamicGBean.java
  ===================================================================
  /**
   *
   * Copyright 2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  package org.apache.geronimo.kernel;
  
  import org.apache.geronimo.gbean.DynamicGBean;
  import org.apache.geronimo.gbean.GBeanInfo;
  import org.apache.geronimo.gbean.GBeanInfoFactory;
  
  /**
   * @version $Revision: 1.1 $ $Date: 2004/03/18 10:04:50 $
   */
  public class MockDynamicGBean implements DynamicGBean {
  
      private static final GBeanInfo GBEAN_INFO;
  
      public static final String MUTABLE_INT_ATTRIBUTE_NAME = "MutableInt";
  
      private int mutableInt;
  
      public Object getAttribute(String name) throws Exception {
          if (MUTABLE_INT_ATTRIBUTE_NAME.equals(name)) {
              return new Integer(mutableInt);
          }
          return null;
      }
  
      public void setAttribute(String name, Object value) throws Exception {
          if (MUTABLE_INT_ATTRIBUTE_NAME.equals(name)) {
              mutableInt = ((Integer) value).intValue();
              return;
          }
          throw new IllegalArgumentException(name + " attribute not supported");
      }
  
      public Object invoke(String name, Object[] arguments, String[] types) throws Exception {
          return null;
      }
  
      /**
       * @return GBeanInfo of this GBean
       */
      public static GBeanInfo getGBeanInfo() {
          return GBEAN_INFO;
      }
  
      static {
          GBeanInfoFactory infoFactory = new GBeanInfoFactory("MockDynamicGBean", MockDynamicGBean.class.getName());
          infoFactory.addAttribute("MutableInt", false);
          GBEAN_INFO = infoFactory.getBeanInfo();
      }
  }
  
  
  
  1.5       +18 -2     incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/gbean/DynamicGAttributeInfo.java
  
  Index: DynamicGAttributeInfo.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/gbean/DynamicGAttributeInfo.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DynamicGAttributeInfo.java	10 Mar 2004 09:59:00 -0000	1.4
  +++ DynamicGAttributeInfo.java	18 Mar 2004 10:04:50 -0000	1.5
  @@ -18,19 +18,35 @@
   package org.apache.geronimo.gbean;
   
   /**
  - * 
  + * Describes an attibute of a GBean.
    * 
    * @version $Revision$ $Date$
    */
   public class DynamicGAttributeInfo extends GAttributeInfo {
  +    
  +    /**
  +     * Creates a non-persistent, reabable and writable GAttributeInfo
  +     * 
  +     * @param name
  +     */
       public DynamicGAttributeInfo(String name) {
           this(name, false, true, true);
       }
   
  +    /**
  +     * @param name
  +     * @param persistent
  +     */
       public DynamicGAttributeInfo(String name, boolean persistent) {
           this(name, persistent, true, true);
       }
   
  +    /**
  +     * @param name
  +     * @param persistent
  +     * @param readable
  +     * @param writable
  +     */
       public DynamicGAttributeInfo(String name, boolean persistent, boolean readable, boolean writable) {
           super(name, persistent, Boolean.valueOf(readable), Boolean.valueOf(writable), null, null);
       }
  
  
  
  1.17      +8 -21     incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/gbean/GBeanInfoFactory.java
  
  Index: GBeanInfoFactory.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/gbean/GBeanInfoFactory.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- GBeanInfoFactory.java	10 Mar 2004 09:59:00 -0000	1.16
  +++ GBeanInfoFactory.java	18 Mar 2004 10:04:50 -0000	1.17
  @@ -14,7 +14,6 @@
    *  See the License for the specific language governing permissions and
    *  limitations under the License.
    */
  -
   package org.apache.geronimo.gbean;
   
   import java.lang.reflect.Method;
  @@ -26,7 +25,6 @@
   import java.util.List;
   import java.util.Map;
   import java.util.Set;
  -
   import org.apache.geronimo.kernel.jmx.MBeanOperationSignature;
   
   /**
  @@ -73,7 +71,6 @@
       public GBeanInfoFactory(String name, String className, GBeanInfo source) {
           checkNotNull(name);
           checkNotNull(className);
  -
           this.name = name;
           this.className = className;
           if (source != null) {
  @@ -84,14 +81,12 @@
                       attributes.put(attributeInfo.getName(), attributeInfo);
                   }
               }
  -
               Set sourceOperations = source.getOperations();
               if (sourceOperations != null && !sourceOperations.isEmpty()) {
                   for (Iterator it = sourceOperations.iterator(); it.hasNext();) {
                       GOperationInfo operationInfo = (GOperationInfo) it.next();
  -                    operations.put(
  -                            new MBeanOperationSignature(operationInfo.getName(), operationInfo.getParameterList()),
  -                            operationInfo);
  +                    operations.put(new MBeanOperationSignature(operationInfo.getName(),
  +                            operationInfo.getParameterList()), operationInfo);
                   }
               }
               references.addAll(source.getReferences());
  @@ -104,7 +99,7 @@
       /**
        * Checks whether or not the input argument is null; otherwise it throws
        * {@link IllegalArgumentException}.
  -     *
  +     * 
        * @param clazz the input argument to validate
        * @throws IllegalArgumentException if input is null
        */
  @@ -118,7 +113,7 @@
       /**
        * Checks whether or not the input argument is null; otherwise it throws
        * {@link IllegalArgumentException}.
  -     *
  +     * 
        * @param string the input argument to validate
        * @throws IllegalArgumentException if input is null
        */
  @@ -135,7 +130,6 @@
   
       public void addInterface(Class intf, String[] persistentAttributes) {
           Set persistentName = new HashSet(Arrays.asList(persistentAttributes));
  -
           Method[] methods = intf.getMethods();
           for (int i = 0; i < methods.length; i++) {
               Method method = methods[i];
  @@ -188,9 +182,8 @@
       }
   
       public void addOperation(GOperationInfo operationInfo) {
  -        operations.put(
  -                new MBeanOperationSignature(operationInfo.getName(), operationInfo.getParameterList()),
  -                operationInfo);
  +        operations.put(new MBeanOperationSignature(operationInfo.getName(), operationInfo.getParameterList()),
  +                       operationInfo);
       }
   
       public void addOperation(String name) {
  @@ -214,13 +207,7 @@
       }
   
       public GBeanInfo getBeanInfo() {
  -        return new GBeanInfo(
  -                name,
  -                className,
  -                attributes.values(),
  -                constructor,
  -                operations.values(),
  -                references,
  +        return new GBeanInfo(name, className, attributes.values(), constructor, operations.values(), references,
                   notifications);
       }
   }
  
  
  
  1.10      +7 -11     incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBeanAttribute.java
  
  Index: GBeanMBeanAttribute.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBeanAttribute.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- GBeanMBeanAttribute.java	13 Mar 2004 23:46:30 -0000	1.9
  +++ GBeanMBeanAttribute.java	18 Mar 2004 10:04:50 -0000	1.10
  @@ -106,8 +106,7 @@
                   getInvoker = new MethodInvoker() {
   
                       public Object invoke(Object target, Object[] arguments) throws Exception {
  -                        DynamicGBean dynamicGBean = (DynamicGBean) GBeanMBeanAttribute.this.gmbean.getTarget();
  -                        return dynamicGBean.getAttribute(name);
  +                        return ((DynamicGBean) target).getAttribute(name);
                       }
                   };
               } else {
  @@ -118,8 +117,7 @@
                   setInvoker = new MethodInvoker() {
   
                       public Object invoke(Object target, Object[] arguments) throws Exception {
  -                        DynamicGBean dynamicGBean = (DynamicGBean) GBeanMBeanAttribute.this.gmbean.getTarget();
  -                        dynamicGBean.setAttribute(name, arguments[0]);
  +                        ((DynamicGBean) target).setAttribute(name, arguments[0]);
                           return null;
                       }
                   };
  @@ -209,8 +207,6 @@
           if (persistent && type.isPrimitive()) {
               if (type == Boolean.TYPE) {
                   persistentValue = Boolean.FALSE;
  -            } else if (type == Character.TYPE) {
  -                persistentValue = new Character((char) 0);
               } else if (type == Byte.TYPE) {
                   persistentValue = new Byte((byte) 0);
               } else if (type == Short.TYPE) {
  @@ -219,12 +215,12 @@
                   persistentValue = new Integer(0);
               } else if (type == Long.TYPE) {
                   persistentValue = new Long(0);
  +            } else if (type == Character.TYPE) {
  +                persistentValue = new Character((char) 0);
               } else if (type == Float.TYPE) {
                   persistentValue = new Float(0);
  -            } else if (type == Double.TYPE) {
  +            } else /** if (type == Double.TYPE) */ {
                   persistentValue = new Double(0);
  -            } else {
  -                throw new IllegalArgumentException("Unknown primitive type: " + type.getName());
               }
           }
       }
  @@ -407,7 +403,7 @@
               }
           } else {
               // even though we have an exact name we need to search the methods
  -            // becaus we don't know the parameter type
  +            // because we don't know the parameter type
               Method[] methods = gMBean.getType().getMethods();
               String setterName = attributeInfo.getSetterName();
               for (int i = 0; i < methods.length; i++) {
  
  
  
  1.2       +236 -21   incubator-geronimo/modules/kernel/src/test/org/apache/geronimo/gbean/jmx/GBeanMBeanAttributeTest.java
  
  Index: GBeanMBeanAttributeTest.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/kernel/src/test/org/apache/geronimo/gbean/jmx/GBeanMBeanAttributeTest.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- GBeanMBeanAttributeTest.java	13 Mar 2004 23:46:30 -0000	1.1
  +++ GBeanMBeanAttributeTest.java	18 Mar 2004 10:04:50 -0000	1.2
  @@ -21,9 +21,11 @@
   
   import junit.framework.TestCase;
   
  +import org.apache.geronimo.gbean.DynamicGAttributeInfo;
   import org.apache.geronimo.gbean.GAttributeInfo;
   import org.apache.geronimo.gbean.InvalidConfigurationException;
   import org.apache.geronimo.kernel.Kernel;
  +import org.apache.geronimo.kernel.MockDynamicGBean;
   import org.apache.geronimo.kernel.MockGBean;
   
   /**
  @@ -45,8 +47,16 @@
           }
       }
   
  +    /**
  +     * Wraps GBean
  +     */
       private GBeanMBean gmbean = null;
   
  +    /**
  +     * Wraps DynamicGBean
  +     */
  +    private GBeanMBean dynamicGmbean = null;
  +
       private MethodInvoker getInvoker = null;
   
       private MethodInvoker setInvoker = null;
  @@ -110,6 +120,178 @@
               fail("InvalidConfigurationException expected");
           } catch (InvalidConfigurationException expected) {
           }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo(attributeName, false, Boolean.TRUE, Boolean.FALSE,
  +                    null, null);
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +            assertTrue(attribute.isReadable());
  +            assertFalse(attribute.isWritable());
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo(persistentPrimitiveAttributeName, false,
  +                    Boolean.FALSE, Boolean.TRUE, null, null);
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +            assertFalse(attribute.isReadable());
  +            assertTrue(attribute.isWritable());
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("AnotherFinalInt", false, Boolean.TRUE,
  +                    Boolean.TRUE, null, null);
  +            try {
  +                new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +                fail("Getter and setter methods do not have the same types; InvalidConfigurationException expected");
  +            } catch (InvalidConfigurationException expected) {
  +            }
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("FinalInt", false);
  +            try {
  +                new GBeanMBeanAttribute(gmbean, attributeInfo, String.class);
  +                fail("Constructor argument and getter method do not have the same type; InvalidConfigurationException expected");
  +            } catch (InvalidConfigurationException expected) {
  +            }
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("YetAnotherFinalInt", false);
  +            try {
  +                new GBeanMBeanAttribute(gmbean, attributeInfo, String.class);
  +                fail("Constructor argument and setter method do not have the same type; InvalidConfigurationException expected");
  +            } catch (InvalidConfigurationException expected) {
  +            }
  +        }
  +
  +        {
  +            // the attribute name and getter name are different, yet both
  +            // exist.
  +            // getYetAnotherFinalInt doesn't exist
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("YetAnotherFinalInt", true, "getFinalInt", null);
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +            assertNotNull(attribute);
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("YetAnotherFinalInt", true, null,
  +                    "setCharAsYetAnotherFinalInt");
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +            assertNotNull(attribute);
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("YetAnotherFinalInt", true, null,
  +                    "setBooleanAsYetAnotherFinalInt");
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +            assertNotNull(attribute);
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("YetAnotherFinalInt", true, null,
  +                    "setByteAsYetAnotherFinalInt");
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +            assertNotNull(attribute);
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("YetAnotherFinalInt", true, null,
  +                    "setShortAsYetAnotherFinalInt");
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +            assertNotNull(attribute);
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("YetAnotherFinalInt", true, null,
  +                    "setLongAsYetAnotherFinalInt");
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +            assertNotNull(attribute);
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("YetAnotherFinalInt", true, null,
  +                    "setFloatAsYetAnotherFinalInt");
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +            assertNotNull(attribute);
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("YetAnotherFinalInt", true, null,
  +                    "setDoubleAsYetAnotherFinalInt");
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +            assertNotNull(attribute);
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("YetAnotherFinalInt", true,
  +                    "getVoidGetterOfFinalInt", null);
  +            try {
  +                GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +                fail("Getter method not found on target; InvalidConfigurationException expected");
  +            } catch (InvalidConfigurationException expected) {
  +            }
  +        }
  +
  +        {
  +            final GAttributeInfo attributeInfo = new GAttributeInfo("YetAnotherFinalInt", true, null,
  +                    "setThatDoesntExist");
  +            try {
  +                GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeInfo, null);
  +                fail("Setter method not found on target; InvalidConfigurationException expected");
  +            } catch (InvalidConfigurationException expected) {
  +            }
  +        }
  +
  +        {
  +            final DynamicGAttributeInfo dynamicAttributeInfo = new DynamicGAttributeInfo(attributeName);
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, dynamicAttributeInfo, null);
  +            assertFalse(attribute.isPersistent());
  +            assertEquals(dynamicAttributeInfo.isPersistent(), attribute.isPersistent());
  +            assertTrue(attribute.isReadable());
  +            assertEquals(dynamicAttributeInfo.isReadable().booleanValue(), attribute.isReadable());
  +            assertTrue(attribute.isWritable());
  +            assertEquals(dynamicAttributeInfo.isWritable().booleanValue(), attribute.isWritable());
  +            assertEquals(dynamicAttributeInfo.getName(), attribute.getName());
  +        }
  +
  +        {
  +            final DynamicGAttributeInfo dynamicAttributeInfo = new DynamicGAttributeInfo(attributeName, true);
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, dynamicAttributeInfo, null);
  +            assertTrue(attribute.isPersistent());
  +            assertEquals(dynamicAttributeInfo.isPersistent(), attribute.isPersistent());
  +            assertTrue(attribute.isReadable());
  +            assertEquals(dynamicAttributeInfo.isReadable().booleanValue(), attribute.isReadable());
  +            assertTrue(attribute.isWritable());
  +            assertEquals(dynamicAttributeInfo.isWritable().booleanValue(), attribute.isWritable());
  +            assertEquals(dynamicAttributeInfo.getName(), attribute.getName());
  +        }
  +
  +        {
  +            final DynamicGAttributeInfo dynamicAttributeInfo = new DynamicGAttributeInfo(attributeName, true, false,
  +                    true);
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, dynamicAttributeInfo, null);
  +            assertTrue(attribute.isPersistent());
  +            assertEquals(dynamicAttributeInfo.isPersistent(), attribute.isPersistent());
  +            assertFalse(attribute.isReadable());
  +            assertEquals(dynamicAttributeInfo.isReadable().booleanValue(), attribute.isReadable());
  +            assertTrue(attribute.isWritable());
  +            assertEquals(dynamicAttributeInfo.isWritable().booleanValue(), attribute.isWritable());
  +            assertEquals(dynamicAttributeInfo.getName(), attribute.getName());
  +        }
  +
  +        {
  +            final DynamicGAttributeInfo dynamicAttributeInfo = new DynamicGAttributeInfo(attributeName, true, false,
  +                    false);
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, dynamicAttributeInfo, null);
  +            assertTrue(attribute.isPersistent());
  +            assertEquals(dynamicAttributeInfo.isPersistent(), attribute.isPersistent());
  +            assertFalse(attribute.isReadable());
  +            assertEquals(dynamicAttributeInfo.isReadable().booleanValue(), attribute.isReadable());
  +            assertFalse(attribute.isWritable());
  +            assertEquals(dynamicAttributeInfo.isWritable().booleanValue(), attribute.isWritable());
  +            assertEquals(dynamicAttributeInfo.getName(), attribute.getName());
  +        }
       }
   
       public final void testOnline() throws Exception {
  @@ -129,7 +311,8 @@
                   fail("Setter upon call with " + valueThatCausesException + " should have thrown exception");
               } catch (/* IllegalArgument */Exception expected) {
               } finally {
  -                // @todo possible BUG: gmbean holds information on being online although kernel is shutdown
  +                // @todo possible BUG: gmbean holds information on being online
  +                // although kernel is shutdown
                   // explicit unloading GBean
                   kernel.unloadGBean(name);
                   kernel.shutdown();
  @@ -192,28 +375,59 @@
       }
   
       public final void testGetValue() throws Exception {
  -        // attribute that isn't readable and persistent
  -        final GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeName, String.class, null,
  -                setInvoker);
  -        try {
  -            attribute.getValue();
  -            fail("Only persistent attributes can be accessed while offline; exception expected");
  -        } catch (/* IllegalState */Exception expected) {
  +        {
  +            // attribute that isn't readable and persistent
  +            final GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeName, String.class, null,
  +                    setInvoker);
  +            try {
  +                attribute.getValue();
  +                fail("Only persistent attributes can be accessed while offline; exception expected");
  +            } catch (/* IllegalState */Exception expected) {
  +            }
  +        }
  +
  +        {
  +            final GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(gmbean, attributeName, String.class, null,
  +                    setInvoker);
  +
  +            final ObjectName name = new ObjectName("test:name=MyMockGBean");
  +
  +            final Kernel kernel = new Kernel("test.kernel", "test");
  +            try {
  +                kernel.boot();
  +                kernel.loadGBean(name, gmbean);
  +                kernel.startGBean(name);
  +
  +                attribute.getValue();
  +                fail("This attribute is not readable; exception expected");
  +            } catch (/* IllegalArgument */Exception expected) {
  +            } finally {
  +                kernel.shutdown();
  +            }
           }
   
  -        final ObjectName name = new ObjectName("test:name=MyMockGBean");
  +        {
  +            final DynamicGAttributeInfo dynamicAttributeInfo = new DynamicGAttributeInfo(
  +                    MockDynamicGBean.MUTABLE_INT_ATTRIBUTE_NAME, true, true, true);
  +            GBeanMBeanAttribute attribute = new GBeanMBeanAttribute(dynamicGmbean, dynamicAttributeInfo, null);
  +            final ObjectName name = new ObjectName("test:name=MyMockDynamicGBean");
  +
  +            final Kernel kernel = new Kernel("test.kernel", "test");
  +            try {
  +                kernel.boot();
  +                kernel.loadGBean(name, dynamicGmbean);
  +                kernel.startGBean(name);
  +
  +                final Integer zero = new Integer(0);
  +                assertEquals(zero, attribute.getValue());
  +
  +                final Integer one = new Integer(1);
  +                attribute.setValue(one);
  +                assertEquals(one, attribute.getValue());
  +            } finally {
  +                kernel.shutdown();
  +            }
   
  -        final Kernel kernel = new Kernel("test.kernel", "test");
  -        try {
  -            kernel.boot();
  -            kernel.loadGBean(name, gmbean);
  -            kernel.startGBean(name);
  -
  -            attribute.getValue();
  -            fail("This attribute is not readable; exception expected");
  -        } catch (/* IllegalArgument */Exception expected) {
  -        } finally {
  -            kernel.shutdown();
           }
       }
   
  @@ -323,6 +537,7 @@
   
       protected void setUp() throws Exception {
           gmbean = new GBeanMBean(MockGBean.getGBeanInfo());
  +        dynamicGmbean = new GBeanMBean(MockDynamicGBean.getGBeanInfo());
           getInvoker = new MethodInvoker() {
   
               public Object invoke(Object target, Object[] arguments) throws Exception {