Class BeanInfoGen

java.lang.Object
com.mchange.v2.codegen.bean.BeanInfoGen

public final class BeanInfoGen extends Object
Generates the Java source of an explicit java.beans.BeanInfo class for a bean class. By default the generated BeanInfo fully replicates the information that ordinary introspection would have produced in the absence of any explicit BeanInfo for the bean class -- its bean descriptor, property descriptors, event-set descriptors and method descriptors. Properties may be excluded from the generated property descriptors in two ways: by name (any property whose name appears in excludedPropertyNames) and by type (any property whose type is assignable to one of the Class objects in excludedPropertyTypes). For an indexed property, exclusion by type considers both the array type and the element type, independent of which accessor convention defined the property (an array-valued accessor such as String[] getTags(), a single-index accessor such as String getTags(int), or both). Whichever of the two types the property descriptor does not directly report is derived from the other, and the property is excluded if either is assignable to an excluded type. Thus an indexed property with element type String is excluded whether String.class or String[].class is given, and identically regardless of how it was declared. Because the generated getPropertyDescriptors() returns a non-null array, the JavaBeans Introspector uses it verbatim rather than rediscovering properties reflectively, so the accessor methods of an excluded property are no longer seen as constituting a JavaBeans property. The methods themselves remain ordinary public methods and are still reported among the method descriptors.
  • Method Details

    • explicitBeanInfoClassSourceForBeanClass

      public static String explicitBeanInfoClassSourceForBeanClass(Class beanClass, Set excludedPropertyNames, Set excludedPropertyTypes) throws IntrospectionException, IOException
      Convenience overload equivalent to explicitBeanInfoClassSourceForBeanClass(Class, Set, Set, boolean, boolean) with suppressDescriptorCaching and includeMLogging both false. The generated BeanInfo therefore caches its descriptors (see the multi-argument overload for the trade-offs that implies) and silently omits any descriptor that proves invalid at runtime.
      Throws:
      IntrospectionException
      IOException
    • explicitBeanInfoClassSourceForBeanClass

      public static String explicitBeanInfoClassSourceForBeanClass(Class beanClass, Set excludedPropertyNames, Set excludedPropertyTypes, boolean suppressDescriptorCaching, boolean includeMLogging) throws IntrospectionException, IOException
      Generates Java source for an explicit BeanInfo class describing beanClass.

      Descriptor caching (suppressDescriptorCaching)

      When suppressDescriptorCaching is false (the default), the generated BeanInfo computes its BeanDescriptor and its property, event-set, and method descriptor arrays once, into instance fields, and each accessor returns that cached state (handing back a defensive clone() of the arrays). This matches how the class is actually consumed: Introspector maintains its own per-class cache of BeanInfo instances and reuses a single instance for every introspection of the bean, so regenerating and re-validating every descriptor on each accessor call would be almost pure waste.

      Caching has a cost, though, and it is not primarily about CPU. The cached descriptor objects are shared across all callers, and java.beans descriptors are mutable (setShortDescription, setValue, setBound, setExpert, etc.). Because the Introspector caches the BeanInfo instance, a single caller that mutates a returned descriptor poisons that shared object for every future caller, process-wide and indefinitely. The defensive array clone() protects the membership of each descriptor set (no caller can add or remove descriptors), but it does not protect the mutable state within a descriptor.

      Set suppressDescriptorCaching to true to have every accessor rebuild its descriptors fresh on each call. This is slower and produces more garbage, but it is the only configuration that gives true per-caller isolation: a mutation by one caller cannot propagate to other callers or persist into the future. (Java's bean APIs offer no read-only descriptor variant, and copy-on-read in the cached case would defeat caching entirely, so this binary flag is the practical seam.) Prefer it for security-sensitive deployments in which untrusted code may receive the BeanInfo and could mutate its descriptors.

      Resilience logging (includeMLogging)

      A generated BeanInfo may run on a JVM or library version where some method, property, or event that existed when it was generated is no longer present; such descriptors are skipped rather than allowed to abort the whole BeanInfo. When includeMLogging is true, each skip is logged at WARNING via com.mchange.v2.log; when false, skips are silent.

      Parameters:
      suppressDescriptorCaching - if true, rebuild descriptors fresh on every accessor call (isolated but slow) instead of caching and sharing them (fast but mutably shared)
      includeMLogging - if true, log a WARNING whenever a descriptor is skipped because it is not valid in the runtime environment
      Throws:
      IntrospectionException
      IOException
    • main

      public static void main(String[] argv)