db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From to...@apache.org
Subject cvs commit: db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess PersistentFieldAutoProxyImpl.java PersistentFieldIntrospectorImpl.java AbstractPersistentField.java PersistentFieldDirectAccessImpl.java
Date Wed, 24 Mar 2004 17:04:25 GMT
tomdz       2004/03/24 09:04:25

  Modified:    src/java/org/apache/ojb/broker/metadata/fieldaccess
                        PersistentFieldAutoProxyImpl.java
                        PersistentFieldIntrospectorImpl.java
                        AbstractPersistentField.java
                        PersistentFieldDirectAccessImpl.java
  Log:
  Had to rework the AutoProxy field handler as it did not really work
  
  Revision  Changes    Path
  1.6       +202 -117  db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldAutoProxyImpl.java
  
  Index: PersistentFieldAutoProxyImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldAutoProxyImpl.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- PersistentFieldAutoProxyImpl.java	11 Mar 2004 18:16:12 -0000	1.5
  +++ PersistentFieldAutoProxyImpl.java	24 Mar 2004 17:04:25 -0000	1.6
  @@ -15,11 +15,10 @@
    * limitations under the License.
    */
   
  -import java.beans.BeanInfo;
  -import java.beans.Introspector;
   import java.lang.reflect.Field;
   import java.util.Map;
   
  +import org.apache.commons.beanutils.DynaBean;
   import org.apache.commons.collections.FastHashMap;
   import org.apache.ojb.broker.metadata.MetadataException;
   import org.apache.ojb.broker.util.ClassHelper;
  @@ -32,115 +31,123 @@
    * First checks to see if it is a Field, then Property, then DynaBean
    * <p>
    * It will match in that order.
  - *
  - * @author <a href="brian@frums.net">Brian McCallister</a>
  - * @version
    */
  -public class PersistentFieldAutoProxyImpl implements PersistentField
  +public class PersistentFieldAutoProxyImpl extends AbstractPersistentField
   {
       private static final long serialVersionUID = 6148669985786992032L;
   
  -    private PersistentField wrapped;
  -
  -    private static final Class PERSIST_FIELD = PersistentFieldPrivilegedImpl.class;
  -    private static final Class PERSIST_PROPERTY = PersistentFieldIntrospectorImpl.class;
  -    private static final Class PERSIST_DYNA = PersistentFieldDynaBeanAccessImpl.class;
  -
  +    /** The actual field handler */
  +    private AbstractPersistentField wrapped;
  +    /** Whether we actually found a field handler, or it is still the default one */
  +    private boolean hasBeenDetermined = false;
  +    
       /**
        * Contains additional maps with name to PersistentFactory implementation Class
        * instances
        */
       private static Map classToName = new FastHashMap();
   
  +    private static synchronized void addToCache(Class type, String name, Class pfClass)
  +    {
  +        Map nameToImpl = null;
  +        if (classToName.containsKey(type))
  +        {
  +            nameToImpl = (Map) classToName.get(type);
  +        }
  +        else
  +        {
  +            nameToImpl = new FastHashMap();
  +        }
  +        nameToImpl.put(name, pfClass);
  +    }
  +
  +
       /**
        * Being nice to Class.newInstance() seems popular.
        */
       public PersistentFieldAutoProxyImpl()
       {
  +        super();
       }
   
       /**
  -     * Constructor will examine the Class type to attempt to determine what
  -     * type of attribute this is (field, property, or DynaProperty and
  -     * wrap an instance of the correct PersistentField implementation
  -     * for that field.
  -     * <p>
  -     * TODO: Improve error reporting. Really need to keep why
  -     * 		 each one failed and give it lump some to the
  -     * 		 user so that the user can figure out why the one
  -     * 		 which was supposed to work didn't
  +     * Creates a new auto handler object for the indicated field.
  +     * 
  +     * @param type      The type of the object containing the field
  +     * @param fieldName The name of the field
        */
  -    public PersistentFieldAutoProxyImpl(Class type, String name)
  +    public PersistentFieldAutoProxyImpl(Class type, String fieldName)
       {
  -        if (this.tryLoadFromCache(type, name))
  -        {
  -            return;
  -        }
  -
  -        /*
  -         * this switches on a series of exceptions. Sadly, it is the only real way to detect
  -         * which one works. The cache should manage things so this chain only need be called
  -         * once per field. --Brian
  -         */
  +        super(type, fieldName);
  +    }
   
  -        try
  -        {
  -            this.tryFieldImpl(type, name);
  -            return;
  -        }
  -        catch (Exception e)
  -        { // we don't care yet
  -        }
  +    /**
  +     * Creates an instance of the given field handler type.
  +     * 
  +     * @param handlerType The field handler type
  +     * @return The handler instance
  +     * @throws MetadataException If the handler could not be found, or cannot handle the
field
  +     */
  +    private AbstractPersistentField getFieldImpl(Class handlerType) throws MetadataException
  +    {
  +        Class[]  types = { Class.class, String.class };
  +        Object[] args  = { rootObjectType, fieldName };
   
           try
           {
  -            this.tryPropertyImpl(type, name);
  -            return;
  +            return (AbstractPersistentField)ClassHelper.newInstance(handlerType, types,
args);
           }
  -        catch (Exception e1)
  -        { // We still don't care
  -        }
  -
  -        // Only option left is for it to be a dynabean
  -        try
  +        catch (Exception ex)
           {
  -            this.tryDynaBeanImpl(type, name);
  -            return;
  -        }
  -        catch (Exception e)
  -        { // Technically we care, but we are baout to throw an exception anyway
  +            if (ex instanceof MetadataException)
  +            {
  +                throw (MetadataException)ex;
  +            }
  +            else
  +            {
  +                throw new MetadataException(ex);
  +            }
           }
  -
  -        // We couldn't match anything, throw Exception
  -        String message =
  -            "No field, property, or DynaProperty can be found to match " + type.getName()
+ "." + name + "()";
  -        LoggerFactory.getDefaultLogger().warn(message);
  -        throw new MetadataException(message);
       }
   
  -    private void tryDynaBeanImpl(Class type, String name) throws Exception
  +    /**
  +     * Returns an instance of the field-direct handler.
  +     * 
  +     * @return The handler instance
  +     * @throws MetadataException If the handler could not be found, or cannot handle the
field
  +     */
  +    private AbstractPersistentField getDirectImpl() throws MetadataException
       {
  -        Class[] types = { Class.class, String.class };
  -        Object[] args = { type, name };
  -
  -        wrapped = (PersistentField) ClassHelper.newInstance(PERSIST_DYNA, types, args);
  -
  +        return getFieldImpl(PersistentFieldPrivilegedImpl.class);
       }
   
  -    private void tryPropertyImpl(Class type, String name) throws Exception
  +    /**
  +     * Returns an instance of the dyna bean handler.
  +     * 
  +     * @return The handler instance
  +     * @throws MetadataException If the handler could not be found, or cannot handle the
field
  +     */
  +    private AbstractPersistentField getDynaBeanImpl() throws MetadataException
       {
  -        BeanInfo info = Introspector.getBeanInfo(type);
  -        Class[] types = { Class.class, String.class };
  -        Object[] args = { type, name };
  +        return getFieldImpl(PersistentFieldDynaBeanAccessImpl.class);
  +    }
   
  -        wrapped = (PersistentField) ClassHelper.newInstance(PERSIST_PROPERTY, types, args);
  +    /**
  +     * Returns an instance of the bean-property handler.
  +     * 
  +     * @return The handler instance
  +     * @throws MetadataException If the handler could not be found, or cannot handle the
field
  +     */
  +    private AbstractPersistentField getPropertyImpl() throws MetadataException
  +    {
  +        return getFieldImpl(PersistentFieldIntrospectorImpl.class);
       }
   
       /**
        * If it finds an implementation in the cache it will load it into the
        * wrapped field and return true.
        */
  -    private boolean tryLoadFromCache(Class type, String name)
  +    private AbstractPersistentField tryLoadFromCache(Class type, String name)
       {
           if (classToName.containsKey(name))
           {
  @@ -152,7 +159,7 @@
                   Class clazz = (Class) nameToImpl.get(type);
                   try
                   {
  -                    wrapped = (PersistentField) ClassHelper.newInstance(clazz, types, args);
  +                    return (AbstractPersistentField)ClassHelper.newInstance(clazz, types,
args);
                   }
                   catch (Exception e2)
                   {
  @@ -161,93 +168,171 @@
                           e2);
                       throw new MetadataException("Unable to use cached PersistentField:
", e2);
                   }
  -                return true;
               }
           }
  -        return false;
  -    }
  -
  -    private void tryFieldImpl(Class type, String name) throws Exception
  -    {
  -        // Field field = this.getFieldRecursive(type, name);
  -        Class[] types = { Class.class, String.class };
  -        Object[] args = { type, name };
  -
  -        wrapped = (PersistentField) ClassHelper.newInstance(PERSIST_FIELD, types, args);
  -
  +        return null;
       }
   
       /**
  -     * REFACTOR: This is cut and paste code from PersistentFieldDefaultImpl,
  -     *
  -     * @throws NoSuchFieldException if no Field was found into the class hierarchy
  +     * Returns the actual field handler. If none is determined yet, it first tries to
  +     * find one for the field.
  +     * 
  +     * @return The wrapped field handler
  +     * @throws MetadataException If no handler for the field could be found
        */
  -    protected Field getFieldRecursive(Class c, String name) throws NoSuchFieldException
  +    private AbstractPersistentField getWrapped() throws MetadataException
       {
  +        // 1. direct field 
  +        // 2. bean
  +        // 3. dyna bean
  +        if (wrapped != null)
  +        {
  +            return wrapped;
  +        }
  +        // TODO: caching
  +        /*
  +        wrapped = tryLoadFromCache(rootObjectType, fieldName);
  +        if (wrapped != null)
  +        {
  +            return wrapped;
  +        }
  +        */
  +
  +        /*
  +         * this switches on a series of exceptions. Sadly, it is the only real way to detect
  +         * which one works. The cache should manage things so this chain only need be called
  +         * once per field. --Brian
  +         */
  +
           try
           {
  -            Field f = c.getDeclaredField(name);
  -            return f;
  +            Field field = AbstractPersistentField.computeField(rootObjectType, fieldName,
isNestedField(), false);
  +
  +            wrapped           = getDirectImpl();
  +            hasBeenDetermined = true;
  +            return wrapped;
           }
  -        catch (NoSuchFieldException e)
  +        catch (MetadataException ex)
           {
  -            // if field  could not be found in the inheritance hierarchy, signal error
  -            if (c == Object.class)
  -            {
  -                throw e;
  -            }
  -            // if field could not be found in class c try in superclass
  -            else
  +            // no direct field to use
  +        }
  +
  +        try
  +        {
  +            if (PersistentFieldIntrospectorImpl.findPropertyDescriptor(rootObjectType,
fieldName) != null)
               {
  -                return getFieldRecursive(c.getSuperclass(), name);
  +                wrapped           = getPropertyImpl();
  +                hasBeenDetermined = true;
  +                return wrapped;
               }
           }
  -    }
  +        catch (MetadataException ex)
  +        {
  +            // no bean property either
  +        }
   
  -    private static synchronized void addToCache(Class type, String name, Class pfClass)
  -    {
  -        Map nameToImpl = null;
  -        if (classToName.containsKey(type))
  +        // Only option left is for it to be a dynabean which we'll use as the default
  +        // as we can check it only when actually doing something
  +        // of course, we can only use the dyna bean if the library is present
  +        try
           {
  -            nameToImpl = (Map) classToName.get(type);
  +            wrapped = getDynaBeanImpl();
  +            return wrapped;
           }
  -        else
  +        catch (NoClassDefFoundError ex)
           {
  -            nameToImpl = new FastHashMap();
  +            String message = "Could not use dyna beans (not in classpath), and no field
or property matches " + rootObjectType.getName() + "." + fieldName;
  +
  +            getLog().error(message);
  +            throw new MetadataException(message);
           }
  -        nameToImpl.put(name, pfClass);
  +    }
  +
  +    /**
  +     * Returns the wrapped field handler. This method is also able to check whether the
default
  +     * handler (dyna bean) can actually be used as it has an actual object whose field
shall be
  +     * accessed (which then must be a dyna bean).
  +     * 
  +     * @param targetObject The object whose field is accessed
  +     * @return The wrapped field handler
  +     * @throws MetadataException If no handler for the field could be found
  +     */
  +    private AbstractPersistentField getWrapped(Object targetObject) throws MetadataException
  +    {
  +        // ensure that we at least tried to find the handler
  +        AbstractPersistentField result = getWrapped();
  +
  +        if (!hasBeenDetermined)
  +        {
  +            // still the default handler, so this is the first time that we can check for
dyna beans
  +            if (targetObject instanceof DynaBean)
  +            {
  +                // the default dyna bean is ok
  +                hasBeenDetermined = true;
  +            }
  +            else
  +            {
  +                // no handler could be found -> error
  +                String message = "No field, property, or DynaProperty can be found to match
" + rootObjectType.getName() + "." + fieldName;
  +
  +                getLog().error(message);
  +                throw new MetadataException(message);
  +            }
  +        }
  +        return result;
       }
   
       /* These are all the implementation methods delagating to the wrapped impl*/
   
  -    public Class getDeclaringClass()
  +    /**
  +     * Set the field value for the given target object.
  +     * 
  +     * @param targetObject The object that contains the field to set
  +     * @param value        The value to set
  +     */
  +    public void doSet(Object targetObject, Object value)
       {
  -        return wrapped.getDeclaringClass();
  +        getWrapped(targetObject).doSet(targetObject, value);
       }
   
  -    public void set(Object obj, Object value) throws MetadataException
  +    /**
  +     * Gets the field value from the given target object.
  +     * 
  +     * @param targetObject The object that contains the field to set
  +     * @return The field's value
  +     */
  +    public Object doGet(Object targetObject)
       {
  -        wrapped.set(obj, value);
  +        return getWrapped(targetObject).doGet(targetObject);
       }
   
  -    public Object get(Object anObject) throws MetadataException
  +    public Class getDeclaringClass()
       {
  -        return wrapped.get(anObject);
  +        return getWrapped().getDeclaringClass();
       }
   
       public boolean usesAccessorsAndMutators()
       {
  -        return wrapped.usesAccessorsAndMutators();
  +        return getWrapped().usesAccessorsAndMutators();
       }
   
       public String getName()
       {
  -        return wrapped.getName();
  +        return getWrapped().getName();
       }
   
       public Class getType()
       {
  -        return wrapped.getType();
  +        return getWrapped().getType();
       }
   
  +    public boolean makeAccessible()
  +    {
  +        return getWrapped().makeAccessible();
  +    }
  +
  +    public String toString()
  +    {
  +        return getWrapped().toString();
  +    }
   }
  
  
  
  1.6       +2 -2      db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldIntrospectorImpl.java
  
  Index: PersistentFieldIntrospectorImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldIntrospectorImpl.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- PersistentFieldIntrospectorImpl.java	11 Mar 2004 18:16:12 -0000	1.5
  +++ PersistentFieldIntrospectorImpl.java	24 Mar 2004 17:04:25 -0000	1.6
  @@ -137,7 +137,7 @@
       /**
        * Get the PropertyDescriptor for aClass and aPropertyName
        */
  -    protected PropertyDescriptor findPropertyDescriptor(Class aClass, String aPropertyName)
  +    protected static PropertyDescriptor findPropertyDescriptor(Class aClass, String aPropertyName)
       {
           BeanInfo info;
           PropertyDescriptor[] pd;
  
  
  
  1.16      +8 -8      db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/AbstractPersistentField.java
  
  Index: AbstractPersistentField.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/AbstractPersistentField.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- AbstractPersistentField.java	11 Mar 2004 18:16:12 -0000	1.15
  +++ AbstractPersistentField.java	24 Mar 2004 17:04:25 -0000	1.16
  @@ -128,7 +128,7 @@
       {
           if (field == null)
           {
  -            field = computeField(rootObjectType, fieldName);
  +            field = computeField(rootObjectType, fieldName, isNestedField(), makeAccessible());
           }
           return field;
       }
  @@ -141,12 +141,12 @@
        * @throws MetadataException if there is an error computing the field
        * ( No Field was found into the class hierarchy)
        */
  -    private Field computeField(Class c, String fieldname)
  +    protected static Field computeField(Class c, String fieldname, boolean isNested, boolean
makeAccessible)
       {
           try
           {
               Field f;
  -            if (isNestedField())
  +            if (isNested)
               {
                   f = getNestedRecursiveField(c, fieldname);
               }
  @@ -155,7 +155,7 @@
                   f = getFieldRecursive(c, fieldname);
               }
   
  -            if (makeAccessible())
  +            if (makeAccessible)
               {
                   f.setAccessible(true);
               }
  @@ -171,7 +171,7 @@
        * try to find a field in class c, recurse through class hierarchy if necessary
        * @throws NoSuchFieldException if no Field was found into the class hierarchy
        */
  -    private Field getFieldRecursive(Class c, String name) throws NoSuchFieldException
  +    private static Field getFieldRecursive(Class c, String name) throws NoSuchFieldException
       {
           try
           {
  @@ -181,7 +181,7 @@
           catch (NoSuchFieldException e)
           {
               // if field  could not be found in the inheritance hierarchy, signal error
  -            if (c == Object.class)
  +            if ((c == Object.class) || (c.getSuperclass() == null) || c.isInterface())
               {
                   throw e;
               }
  @@ -196,7 +196,7 @@
       /**
        * Return field of the given field name path expression
        */
  -    private Field getNestedRecursiveField(Class c, String aFieldName) throws NoSuchFieldException
  +    private static Field getNestedRecursiveField(Class c, String aFieldName) throws NoSuchFieldException
       {
           Field result = null;
           int index = aFieldName.indexOf(PATH_TOKEN);
  
  
  
  1.11      +1 -28     db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldDirectAccessImpl.java
  
  Index: PersistentFieldDirectAccessImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldDirectAccessImpl.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- PersistentFieldDirectAccessImpl.java	11 Mar 2004 18:16:12 -0000	1.10
  +++ PersistentFieldDirectAccessImpl.java	24 Mar 2004 17:04:25 -0000	1.11
  @@ -123,33 +123,6 @@
       }
   
       /**
  -     * try to find a field in class c, recurse through class hierarchy if necessary
  -     *
  -     * @throws NoSuchFieldException if no Field was found into the class hierarchy
  -     */
  -    protected Field getFieldRecursive(Class c, String fieldname) throws NoSuchFieldException
  -    {
  -        try
  -        {
  -            Field f = c.getDeclaredField(fieldname);
  -            return f;
  -        }
  -        catch (NoSuchFieldException e)
  -        {
  -            // if field  could not be found in the inheritance hierarchy, signal error
  -            if (c == Object.class)
  -            {
  -                throw e;
  -            }
  -            // if field could not be found in class c try in superclass
  -            else
  -            {
  -                return getFieldRecursive(c.getSuperclass(), fieldname);
  -            }
  -        }
  -    }
  -
  -    /**
        * This implementation returns always 'false'.
        * @see AbstractPersistentField#makeAccessible()
        */
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Mime
View raw message