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 ar...@apache.org on 2003/07/08 03:04:39 UTC
cvs commit: db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess AbstractPersistentField.java PersistentFieldDirectAccessImpl.java PersistentFieldPrivilegedImpl.java
arminw 2003/07/07 18:04:39
Added: src/java/org/apache/ojb/broker/metadata/fieldaccess
AbstractPersistentField.java
PersistentFieldDirectAccessImpl.java
PersistentFieldPrivilegedImpl.java
Log:
add new PersistentField implementations
Revision Changes Path
1.1 db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/AbstractPersistentField.java
Index: AbstractPersistentField.java
===================================================================
package org.apache.ojb.broker.metadata.fieldaccess;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.ojb.broker.metadata.MetadataException;
import org.apache.ojb.broker.util.ProxyHelper;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
import java.lang.reflect.Field;
/**
* Abstract {@link PersistentField} implementation.
*
* @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
* @version $Id: AbstractPersistentField.java,v 1.1 2003/07/08 01:04:39 arminw Exp $
*/
public abstract class AbstractPersistentField implements PersistentField
{
public static final String PATH_TOKEN = "::";
public static final Class PERSISTENT_FIELD_IMPL_FOR_NESTED = PersistentFieldDirectAccessImpl.class;
private static final int NORMAL_FIELD = 1;
private static final int NESTED_FIELD = 2;
private static final Class[] METHOD_TYPES = {Class.class, String.class};
private transient Field field;
private String fieldName;
private Class rootObjectType;
/**
* 0 - not initialized
* 1 - normal field
* 2 - nested field
*/
private int isNestedField;
/**
* For internal use only!!
*/
protected AbstractPersistentField()
{
}
public AbstractPersistentField(Class clazz, String fieldname)
{
this.rootObjectType = clazz;
this.fieldName = fieldname;
}
/**
* Set value for target object.
*/
public abstract void doSet(Object targetObject, Object value);
/**
* Get value for field extracted from given target object.
*/
public abstract Object doGet(Object targetObject);
/**
* A value of true indicates that this field should
* suppress Java language access checking when it is used.
*/
public abstract boolean makeAccessible();
/**
* do not override this method, have a look at {@link doSet}
*/
public void set(Object targetObject, Object value) throws MetadataException
{
if (isNestedField())
{
setNestedObject(targetObject, fieldName, value);
}
else
{
doSet(targetObject, value);
}
}
/**
* do not override this method, have a look at {@link doGet}
*/
public Object get(Object targetObject) throws MetadataException
{
if (isNestedField())
{
return getNestedObject(targetObject, fieldName);
}
else
{
return doGet(targetObject);
}
}
protected Logger getLog()
{
return LoggerFactory.getLogger("PersistentField");
}
/**
* Returns the underlying field object.
* If parameter <tt>setAccessible</tt> is true the
* field access checking was suppressed.
*/
protected Field getField()
{
if (field == null)
{
field = computeField(rootObjectType, fieldName);
}
return field;
}
/**
* Tries to compute a Field object using getFieldRecursive.
* @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)
{
try
{
Field f = getFieldRecursive(c, fieldname);
if (makeAccessible()) f.setAccessible(true); // allow access to private members
return f;
}
catch (NoSuchFieldException e)
{
throw new MetadataException("Can't find member " + fieldname + " in " + c.getName(), e);
}
}
/**
* 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
{
try
{
Field f = c.getDeclaredField(name);
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(), name);
}
}
}
protected boolean isNestedField()
{
if (isNestedField == 0) // not initialized
{
if (fieldName == null)
{
throw new MetadataException(
"Unexpected behaviour: fieldName is null, can not calculate field rootObjectType");
}
if (fieldName.indexOf(PATH_TOKEN) >= 0)
{
isNestedField = NESTED_FIELD;
}
else
{
isNestedField = NORMAL_FIELD;
}
}
return isNestedField == NESTED_FIELD;
}
/**
* Get nested attribute with given field name.
* @param obj object from which the represented field's value is to be extracted
* @param fieldName nested attribute name
* @return Object the value of the represented field in object obj
*/
protected Object getNestedObject(Object obj, String fieldName)
{
Object result = null;
int index = fieldName.indexOf(PATH_TOKEN);
if (index >= 0)
{
String name = fieldName.substring(0, index);
PersistentField pField = createInternPersistentField(ProxyHelper.getRealClass(obj), name);
Object attrib = pField.get(ProxyHelper.getRealObject(obj));
if (attrib != null)
{
String nestedName = fieldName.substring(index + PATH_TOKEN.length());
result = getNestedObject(attrib, nestedName);
}
}
else
{
PersistentField pField = createInternPersistentField(ProxyHelper.getRealClass(obj), fieldName);
result = pField.get(ProxyHelper.getRealObject(obj));
}
return result;
}
/**
* Set nested attribute with given value.
* @param obj the object whose field should be modified
* @param fieldName nested attribute name
* @param value the new value for the field of obj being modified
*/
protected void setNestedObject(Object obj, String fieldName, Object value)
{
int index = fieldName.indexOf(PATH_TOKEN);
if (index >= 0)
{
String name = fieldName.substring(0, index);
AbstractPersistentField pField = createInternPersistentField(ProxyHelper.getRealClass(obj), name);
Object attrib = pField.get(ProxyHelper.getRealObject(obj));
if (attrib == null)
{
try
{
attrib = pField.getType().newInstance();
}
catch (InstantiationException e)
{
throw new MetadataException("Error instantiate field: "
+ name + " in object:" + obj.getClass().getName(), e);
}
catch (IllegalAccessException e)
{
throw new MetadataException("Error getting field:"
+ name + " in object:" + obj.getClass().getName(), e);
}
Class type = pField.getType();
if ((value != null) || !type.isPrimitive())
{
pField.doSet(ProxyHelper.getRealObject(obj), attrib);
}
}
//
String nestedName = fieldName.substring(index + PATH_TOKEN.length());
setNestedObject(attrib, nestedName, value);
}
else
{
PersistentField pField = createInternPersistentField(ProxyHelper.getRealClass(obj), fieldName);
pField.set(ProxyHelper.getRealObject(obj), value);
}
}
private AbstractPersistentField createInternPersistentField(Class fieldType, String fieldName)
{
// try
// {
// Object[] args = {fieldType, fieldName};
// return (AbstractPersistentField) ClassHelper.newInstance(PERSISTENT_FIELD_IMPL_FOR_NESTED, METHOD_TYPES, args);
// }
// catch (Exception e)
// {
// throw new MetadataException("Cannot create PersistentField for field '" + fieldName + "' of class " +
// fieldType.getName(), e);
// }
try
{
return (AbstractPersistentField) PersistentFieldFactory.createPersistentField(fieldType, fieldName);
}
catch (Exception e)
{
throw new MetadataException("Cannot create PersistentField for field '" + fieldName + "' of class " +
fieldType.getName(), e);
}
}
public String toString()
{
ToStringBuilder buf = new ToStringBuilder(this, ToStringStyle.DEFAULT_STYLE);
buf.append("isNestedField", isNestedField());
buf.append("fieldName", fieldName);
buf.append("field", field);
return buf.toString();
}
public String getName()
{
return fieldName;
}
public Class getType()
{
return getField().getType();
}
public Class getDeclaringClass()
{
return getField().getDeclaringClass();
}
}
1.1 db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldDirectAccessImpl.java
Index: PersistentFieldDirectAccessImpl.java
===================================================================
package org.apache.ojb.broker.metadata.fieldaccess;
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache ObjectRelationalBridge" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
import org.apache.ojb.broker.metadata.MetadataException;
import org.apache.ojb.broker.util.BrokerHelper;
import org.apache.ojb.broker.util.ProxyHelper;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
import java.lang.reflect.Field;
/**
* This class is a wrapper around java.lang.reflect.Field objects.
* @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
* @version $Id: PersistentFieldDirectAccessImpl.java,v 1.1 2003/07/08 01:04:39 arminw Exp $
*/
public class PersistentFieldDirectAccessImpl extends AbstractPersistentField
{
public PersistentFieldDirectAccessImpl()
{
}
public PersistentFieldDirectAccessImpl(Class type, String fieldname)
{
super(type, fieldname);
}
/**
* Sets the field represented by this PersistentField object on the specified object argument to the specified new value.
* The new value is automatically unwrapped if the underlying field has a primitive type.
* This implementation invokes set() on its underlying Field object if the argument <b>is not null</b>.
* OBS IllegalArgumentExceptions are wrapped as PersistenceBrokerExceptions.
*
* @throws MetadataException if there is an error setting this field value on obj
* @see java.lang.reflect.Field
*/
public void doSet(Object obj, Object value) throws MetadataException
{
Field field = getField();
Class type = field.getType();
try
{
/**
* MBAIRD
* we need to be able to set values to null. We can only set something to null if
* the type is not a primitive (assignable from Object).
*/
// thanks to Tomasz Wysocki for this trick
if ((value != null) || !type.isPrimitive())
{
//System.out.println("## set: "+obj+" -- "+value);
field.set(ProxyHelper.getRealObject(obj), value);
}
}
catch (NullPointerException ignored)
{
getLog().info("Value for field " + (field != null ? field.getName() : null) +
" of type " + type.getName() + " is null. Can't write into null.", ignored);
}
catch (IllegalAccessException e)
{
getLog().error("while set field: " + BrokerHelper.buildMessageString(obj, value, field));
throw new MetadataException("IllegalAccess error setting field:" +
(field != null ? field.getName() : null) + " in object:" + obj.getClass().getName(), e);
}
catch (Exception e)
{
getLog().error("while set field: " + BrokerHelper.buildMessageString(obj, value, field), e);
throw new MetadataException("Error setting field:" + (field != null ? field.getName() : null) +
" in object:" + obj.getClass().getName(), e);
}
}
/**
* Returns the value of the field represented by this PersistentField, on the specified object.
* This implementation invokes get() on its underlying Field object.
*
* @param obj - the object instance which we are trying to get the field value from
* @throws MetadataException if there is an error getting this field value from obj
* @see java.lang.reflect.Field
*/
public Object doGet(Object obj) throws MetadataException
{
Field field = getField();
try
{
Object result = field.get(ProxyHelper.getRealObject(obj));
return result;
}
catch (IllegalAccessException e)
{
throw new MetadataException(
"IllegalAccess error getting field:" +
(field != null ? field.getName() : null) + " in object:" + obj.getClass().getName(), e);
}
catch (Throwable e)
{
throw new MetadataException("Error getting field:" +
(field != null ? field.getName() : null) + " in object:" + obj.getClass().getName(), e);
}
}
/**
* 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()
*/
public boolean makeAccessible()
{
return true;
}
/**
* Always returns 'false'.
* @see PersistentField#usesAccessorsAndMutators
*/
public boolean usesAccessorsAndMutators()
{
return false;
}
}
1.1 db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldPrivilegedImpl.java
Index: PersistentFieldPrivilegedImpl.java
===================================================================
package org.apache.ojb.broker.metadata.fieldaccess;
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache ObjectRelationalBridge" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
import org.apache.ojb.broker.metadata.MetadataException;
import org.apache.ojb.broker.util.BrokerHelper;
import org.apache.ojb.broker.util.ProxyHelper;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* This class is a wrapper around java.lang.reflect.Field objects.
* @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
* @version $Id: PersistentFieldPrivilegedImpl.java,v 1.1 2003/07/08 01:04:39 arminw Exp $
*/
public class PersistentFieldPrivilegedImpl extends PersistentFieldDirectAccessImpl
{
private SetAccessibleAction setAccessibleAction = new SetAccessibleAction();
public PersistentFieldPrivilegedImpl()
{
}
public PersistentFieldPrivilegedImpl(Class type, String fieldname)
{
super(type, fieldname);
}
/**
*
*/
public synchronized void doSet(Object obj, Object value) throws MetadataException
{
int accessibleState = 0;
Field field = getField();
if(!field.isAccessible()) accessibleState = 1;
if(accessibleState == 1)
{
accessibleState = 2;
AccessController.doPrivileged(setAccessibleAction);
}
try
{
super.doSet(obj, value);
}
finally
{
if(accessibleState == 2) field.setAccessible(false);
}
}
/**
*
*/
public synchronized Object doGet(Object obj) throws MetadataException
{
int accessibleState = 0;
Field field = getField();
Object result = null;
if(!field.isAccessible()) accessibleState = 1;
if(accessibleState == 1)
{
accessibleState = 2;
AccessController.doPrivileged(setAccessibleAction);
}
try
{
result = super.doGet(obj);
}
finally
{
if(accessibleState == 2) field.setAccessible(false);
}
return result;
}
/**
* This implementation returns always 'false'.
* @see AbstractPersistentField#makeAccessible()
*/
public boolean makeAccessible()
{
return false;
}
/**
* Always returns 'false'.
* @see PersistentField#usesAccessorsAndMutators
*/
public boolean usesAccessorsAndMutators()
{
return false;
}
//************************************************************
// inner class
//************************************************************
private class SetAccessibleAction implements PrivilegedAction, Serializable
{
public Object run()
{
getField().setAccessible(true);
return null;
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org