You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by to...@apache.org on 2004/03/24 18:04:25 UTC
cvs commit: db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess PersistentFieldAutoProxyImpl.java PersistentFieldIntrospectorImpl.java AbstractPersistentField.java PersistentFieldDirectAccessImpl.java
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