db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mattba...@apache.org
Subject cvs commit: db-ojb/src/java/org/apache/ojb/otm/core BaseConnection.java
Date Mon, 07 Jul 2003 22:54:15 GMT
mattbaird    2003/07/07 15:54:15

  Modified:    src/java/org/apache/ojb/otm/copy ObjectCopyException.java
                        CloneableObjectCopyStrategy.java
                        SerializeObjectCopyStrategy.java OjbCloneable.java
                        ObjectCopyStrategy.java NoOpObjectCopyStrategy.java
               src/java/org/apache/ojb/otm/core BaseConnection.java
  Added:       src/java/org/apache/ojb/otm/copy
                        MetadataObjectCopyStrategy.java
                        ReflectiveObjectCopyStrategy.java
  Log:
  new ObjectCopyStrategy implementations. MetadataObjectCopyStrategy uses the classdescriptor
to copy, ReflectiveObjectCopyStrategy uses reflection.
  
  Revision  Changes    Path
  1.2       +2 -2      db-ojb/src/java/org/apache/ojb/otm/copy/ObjectCopyException.java
  
  Index: ObjectCopyException.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/copy/ObjectCopyException.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ObjectCopyException.java	1 Feb 2003 18:39:57 -0000	1.1
  +++ ObjectCopyException.java	7 Jul 2003 22:54:14 -0000	1.2
  @@ -5,9 +5,9 @@
   /**
    *
    * <javadoc>
  - * 
  + *
    * @author <a href="mailto:rraghuram@hotmail.com">Raghu Rajah</a>
  - * 
  + *
    */
   public class ObjectCopyException extends OTMGenericException
   {
  
  
  
  1.2       +14 -12    db-ojb/src/java/org/apache/ojb/otm/copy/CloneableObjectCopyStrategy.java
  
  Index: CloneableObjectCopyStrategy.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/copy/CloneableObjectCopyStrategy.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- CloneableObjectCopyStrategy.java	1 Feb 2003 18:39:57 -0000	1.1
  +++ CloneableObjectCopyStrategy.java	7 Jul 2003 22:54:14 -0000	1.2
  @@ -1,5 +1,7 @@
   package org.apache.ojb.otm.copy;
   
  +import org.apache.ojb.broker.metadata.DescriptorRepository;
  +
   /* ====================================================================
    * The Apache Software License, Version 1.1
    *
  @@ -53,31 +55,31 @@
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
    */
  - 
  - /**
  -  * @author matthew.baird
  -  */
  +
  +/**
  + * @author matthew.baird
  + */
   public class CloneableObjectCopyStrategy implements ObjectCopyStrategy
   {
   	/**
   	 * If users want to implement clone on all their objects, we can use this
   	 * to make copies. This is hazardous as user may mess it up, but it is also
   	 * potentially the fastest way of making a copy.
  -	 * 
  +	 *
   	 * Usually the OjbCloneable interface should just be delegating to the clone()
   	 * operation that the user has implemented.
  -	 * 
  -     * @see org.apache.ojb.otm.jdo.copy.ObjectCopyStrategy#copy(Object, DescriptorRepository)
  -     * 
  +	 *
  +	 * @see org.apache.ojb.otm.copy.ObjectCopyStrategy#copy(Object, DescriptorRepository)
  +	 *
   	 */
  -	public Object copy (Object obj)
  -        throws ObjectCopyException
  +	public Object copy(Object obj, DescriptorRepository repo)
  +			throws ObjectCopyException
   	{
   		if (obj instanceof OjbCloneable)
   		{
   			try
   			{
  -				return ((OjbCloneable)obj).ojbClone();
  +				return ((OjbCloneable) obj).ojbClone();
   			}
   			catch (Exception e)
   			{
  @@ -87,7 +89,7 @@
   		else
   		{
   			throw new ObjectCopyException("Object must implement OjbCloneable in order to use the"
  -                + " CloneableObjectCopyStrategy");
  +										  + " CloneableObjectCopyStrategy");
   		}
   	}
   }
  
  
  
  1.3       +51 -49    db-ojb/src/java/org/apache/ojb/otm/copy/SerializeObjectCopyStrategy.java
  
  Index: SerializeObjectCopyStrategy.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/copy/SerializeObjectCopyStrategy.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SerializeObjectCopyStrategy.java	28 Jun 2003 12:46:54 -0000	1.2
  +++ SerializeObjectCopyStrategy.java	7 Jul 2003 22:54:14 -0000	1.3
  @@ -54,61 +54,63 @@
    * <http://www.apache.org/>.
    */
   
  -import java.io.ByteArrayInputStream;
  -import java.io.ByteArrayOutputStream;
  -import java.io.IOException;
  -import java.io.ObjectInputStream;
  -import java.io.ObjectOutputStream;
  +import org.apache.ojb.broker.metadata.DescriptorRepository;
  +
  +import java.io.*;
   
   
   /**
    * Does in-memory serialization to achieve a copy of the object graph.
  - * 
  + *
    * @author matthew.baird
    * @see ObjectCopyStrategy
    */
  -public class SerializeObjectCopyStrategy implements ObjectCopyStrategy
  +public final class SerializeObjectCopyStrategy implements ObjectCopyStrategy
   {
  -    /**
  -    * This implementation will probably be slower than the metadata
  -    * object copy, but this was easier to implement.
  -    * @see org.apache.ojb.otm.jdo.copy.ObjectCopyStrategy#copy(Object, DescriptorRepository)
  -    */
  -    public Object copy (Object obj)
  -        throws ObjectCopyException
  -    {
  -        ObjectOutputStream oos = null;
  -        ObjectInputStream ois = null;
  -        try
  -        {
  -            ByteArrayOutputStream bos = new ByteArrayOutputStream();
  -            oos = new ObjectOutputStream(bos);
  -            // serialize and pass the object
  -            oos.writeObject(obj);
  -            oos.flush();
  -            ByteArrayInputStream bin =
  -                new ByteArrayInputStream(bos.toByteArray());
  -            ois = new ObjectInputStream(bin);
  -            // return the new object
  -            return ois.readObject();
  -        }
  -        catch (Exception e)
  -        {
  -            throw new ObjectCopyException(e);
  -        }
  -        finally
  -        {
  -            try
  -            {
  -                oos.close();
  -                if (ois != null) {
  -                    ois.close();
  -                }
  -            }
  -            catch (IOException ioe)
  -            {
  -                // ignore
  -            }
  -        }
  -    }
  +	/**
  +	 * This implementation will probably be slower than the metadata
  +	 * object copy, but this was easier to implement.
  +	 * @see org.apache.ojb.otm.copy.ObjectCopyStrategy#copy(Object, DescriptorRepository)
  +	 */
  +	public Object copy(final Object obj, final DescriptorRepository repo)
  +			throws ObjectCopyException
  +	{
  +		ObjectOutputStream oos = null;
  +		ObjectInputStream ois = null;
  +		try
  +		{
  +			final ByteArrayOutputStream bos = new ByteArrayOutputStream();
  +			oos = new ObjectOutputStream(bos);
  +			// serialize and pass the object
  +			oos.writeObject(obj);
  +			oos.flush();
  +			final ByteArrayInputStream bin =
  +					new ByteArrayInputStream(bos.toByteArray());
  +			ois = new ObjectInputStream(bin);
  +			// return the new object
  +			return ois.readObject();
  +		}
  +		catch (Exception e)
  +		{
  +			throw new ObjectCopyException(e);
  +		}
  +		finally
  +		{
  +			try
  +			{
  +				if (oos != null)
  +				{
  +					oos.close();
  +				}
  +				if (ois != null)
  +				{
  +					ois.close();
  +				}
  +			}
  +			catch (IOException ioe)
  +			{
  +				// ignore
  +			}
  +		}
  +	}
   }
  
  
  
  1.2       +6 -5      db-ojb/src/java/org/apache/ojb/otm/copy/OjbCloneable.java
  
  Index: OjbCloneable.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/copy/OjbCloneable.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- OjbCloneable.java	1 Feb 2003 18:39:57 -0000	1.1
  +++ OjbCloneable.java	7 Jul 2003 22:54:14 -0000	1.2
  @@ -1,4 +1,5 @@
   package org.apache.ojb.otm.copy;
  +
   /* ====================================================================
    * The Apache Software License, Version 1.1
    *
  @@ -52,11 +53,11 @@
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
    */
  - 
  - /**
  -  * @author matthew.baird
  -  */
  - 
  +
  +/**
  + * @author matthew.baird
  + */
  +
   public interface OjbCloneable
   {
   	/**
  
  
  
  1.2       +11 -8     db-ojb/src/java/org/apache/ojb/otm/copy/ObjectCopyStrategy.java
  
  Index: ObjectCopyStrategy.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/copy/ObjectCopyStrategy.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ObjectCopyStrategy.java	1 Feb 2003 18:39:57 -0000	1.1
  +++ ObjectCopyStrategy.java	7 Jul 2003 22:54:14 -0000	1.2
  @@ -1,23 +1,26 @@
   package org.apache.ojb.otm.copy;
   
  +import org.apache.ojb.broker.metadata.DescriptorRepository;
  +
   /**
    *
    * Strategy to copy classes. The ObjectCopyStrategy is used by Cache to copy objects while
shuttling in
    * and out of the cache.
  - * 
  + *
    * @author <a href="mailto:rraghuram@hotmail.com">Raghu Rajah</a>
  - * 
  + *
    */
   public interface ObjectCopyStrategy
   {
   
   	/**
  -	 * 
  -     * Make a copy of the given object
  -     * 
  -	 * @param obj
  -	 * @return Object
  +	 *
  +	 * Make a copy of the given object
  +	 *
  +	 * @param obj object to be copied
  +	 * @param repo if needed for a meta-data type copy
  +	 * @return Object the copy of the object
   	 */
  -	public Object copy(Object obj);
  +	public Object copy(Object obj, DescriptorRepository repo);
   
   }
  
  
  
  1.2       +9 -7      db-ojb/src/java/org/apache/ojb/otm/copy/NoOpObjectCopyStrategy.java
  
  Index: NoOpObjectCopyStrategy.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/copy/NoOpObjectCopyStrategy.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- NoOpObjectCopyStrategy.java	1 Feb 2003 18:39:57 -0000	1.1
  +++ NoOpObjectCopyStrategy.java	7 Jul 2003 22:54:14 -0000	1.2
  @@ -1,5 +1,7 @@
   package org.apache.ojb.otm.copy;
   
  +import org.apache.ojb.broker.metadata.DescriptorRepository;
  +
   /* ====================================================================
    * The Apache Software License, Version 1.1
    *
  @@ -53,25 +55,25 @@
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
    */
  - 
  +
   /**
    * The NoOpObjectCopyStrategy does not make a copy. It merely returns the same object.
    * 
    * For backwards compatability with OJB 0.9, we include a way to no-op copy
    * the object into the transactional context. This means that we are operating
  - * on a live object, and can potentially mess stuff up. This is essentially 
  + * on a live object, and can potentially mess stuff up. This is essentially
    * supporting a uncommitted-read only strategy.
  - * 
  + *
    * @author matthew.baird
    */
   public class NoOpObjectCopyStrategy implements ObjectCopyStrategy
   {
   	/**
  -	 * @see org.apache.ojb.otm.jdo.copy.ObjectCopyStrategy#copy(Object)
  -	 * 
  +	 * @see org.apache.ojb.otm.copy.ObjectCopyStrategy#copy(Object, DescriptorRepository)
  +	 *
   	 */
  -	public Object copy (Object obj)
  -        throws ObjectCopyException
  +	public Object copy(Object obj, DescriptorRepository repo)
  +			throws ObjectCopyException
   	{
   		return obj;
   	}
  
  
  
  1.1                  db-ojb/src/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java
  
  Index: MetadataObjectCopyStrategy.java
  ===================================================================
  package org.apache.ojb.otm.copy;
  
  /* ====================================================================
   * 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.*;
  import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
  
  import java.util.Collection;
  import java.util.Iterator;
  
  /**
   * recursively copies an object based on the ClassDescriptor
   * User: matthew.baird
   * Date: Jul 7, 2003
   * Time: 1:41:58 PM
   */
  public final class MetadataObjectCopyStrategy implements ObjectCopyStrategy
  {
  	/**
  	 * TODO: handle proxies appropriately
  	 * TODO: handle infinite recursion due to looping object model.
  	 * TODO: handle collections appropriately
  	 * @param obj
  	 * @param repo
  	 * @return
  	 */
  	public Object copy(final Object obj, final DescriptorRepository repo)
  	{
  		/**
  		 * if null, return null, duh
  		 */
  		if (obj == null)
  			return null;
  		/**
  		 * if no classdescriptor exists for this object, just return this object, we
  		 * can't copy it.
  		 */
  		final ClassDescriptor cld = repo.getDescriptorFor(obj.getClass());
  		if (cld == null)
  			return obj;
  
  		Object retval;
  		try
  		{
  			retval = obj.getClass().newInstance();
  		}
  		catch (InstantiationException e)
  		{
  			throw new ObjectCopyException("InstantiationException", e);
  		}
  		catch (IllegalAccessException e)
  		{
  			throw new ObjectCopyException("IllegalAccessException", e);
  		}
  		/**
  		 * first copy all the fields
  		 */
  		final FieldDescriptor[] fieldDescs = cld.getFieldDescriptions();
  		for (int i = 0; i < fieldDescs.length; i++)
  		{
  			final FieldDescriptor fd = fieldDescs[i];
  			final PersistentField f = fd.getPersistentField();
  			/**
  			 * somewhat confusing, use the same field descriptor to set the
  			 * value on the copy as the field descriptor used to get the value from the
  			 * object to be copied.
  			 */
  			f.set(retval, f.get(obj));
  		}
  
  		/**
  		 * then copy all the 1:1 references
  		 */
  		final Collection refDescsCol = cld.getObjectReferenceDescriptors();
  		final ObjectReferenceDescriptor[] rds = (ObjectReferenceDescriptor[]) refDescsCol.toArray(new
ObjectReferenceDescriptor[refDescsCol.size()]);
  		for (int i = 0; i < rds.length; i++)
  		{
  			final ObjectReferenceDescriptor rd = rds[i];
  			final PersistentField f = rd.getPersistentField();
  			/**
  			 * recursively copy the referenced objects
  			 */
  			f.set(retval, copy(f.get(obj), repo));
  		}
  		/**
  		 * then copy all the 1:M and M:N references
  		 */
  		final Collection colDescsCol = cld.getCollectionDescriptors();
  		final Iterator it = colDescsCol.iterator();
  		while (it.hasNext())
  		{
  			final CollectionDescriptor cd = (CollectionDescriptor) it.next();
  			final PersistentField f = cd.getPersistentField();
  			final Object collection = f.get(obj);
  			if (collection instanceof Collection)
  			{
  				try
  				{
  					final Collection newCollection = (Collection) collection.getClass().newInstance();
  					final Iterator tempIter = ((Collection) collection).iterator();
  					while (tempIter.hasNext())
  					{
  						newCollection.add(copy(tempIter.next(), repo));
  					}
  					f.set(retval, newCollection);
  				}
  				catch (InstantiationException e)
  				{
  					throw new ObjectCopyException("InstantiationException", e);
  				}
  				catch (IllegalAccessException e)
  				{
  					throw new ObjectCopyException("IllegalAccessException", e);
  				}
  			}
  		}
  		return retval;
  	}
  }
  
  
  
  1.1                  db-ojb/src/java/org/apache/ojb/otm/copy/ReflectiveObjectCopyStrategy.java
  
  Index: ReflectiveObjectCopyStrategy.java
  ===================================================================
  package org.apache.ojb.otm.copy;
  
  /* ====================================================================
   * 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.DescriptorRepository;
  
  import java.lang.reflect.Array;
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Field;
  import java.lang.reflect.Modifier;
  import java.util.*;
  
  /**
   * User: matthew.baird
   * Date: Jul 7, 2003
   * Time: 3:05:22 PM
   */
  public final class ReflectiveObjectCopyStrategy implements ObjectCopyStrategy
  {
  	private static final Set FINAL_IMMUTABLE_CLASSES;
  	private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
  	private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
  
  	static
  	{
  		FINAL_IMMUTABLE_CLASSES = new HashSet(17);
  		FINAL_IMMUTABLE_CLASSES.add(String.class);
  		FINAL_IMMUTABLE_CLASSES.add(Byte.class);
  		FINAL_IMMUTABLE_CLASSES.add(Short.class);
  		FINAL_IMMUTABLE_CLASSES.add(Integer.class);
  		FINAL_IMMUTABLE_CLASSES.add(Long.class);
  		FINAL_IMMUTABLE_CLASSES.add(Float.class);
  		FINAL_IMMUTABLE_CLASSES.add(Double.class);
  		FINAL_IMMUTABLE_CLASSES.add(Character.class);
  		FINAL_IMMUTABLE_CLASSES.add(Boolean.class);
  	}
  
  	/**
  	 * makes a deep clone of the object, using reflection.
  	 * @param toCopy the object you want to copy
  	 * @param repo the descriptor repository, if needed.
  	 * @return
  	 */
  	public final Object copy(final Object toCopy, final DescriptorRepository repo)
  	{
  		return clone(toCopy, new IdentityHashMap(), new HashMap());
  	}
  
  	/*
  	 * class used to cache class metadata info
  	 */
  	private static final class ClassMetadata
  	{
  		Constructor m_noArgConstructor;
  		Field[] m_declaredFields;
  		boolean m_noArgConstructorAccessible;
  		boolean m_fieldsAccessible;
  	}
  
  	private static Object clone(final Object toCopy, final Map objMap, final Map metadataMap)
  	{
  		/**
  		 * first, check to make sure we aren't recursing to some object that we've already copied.
  		 * if the toCopy is in the objMap, just return it.
  		 */
  		if (objMap.containsKey(toCopy)) return objMap.get(toCopy);
  		final Class objClass = toCopy.getClass();
  		final Object retval;
  		if (objClass.isArray())
  		{
  			retval = handleArray(toCopy, objMap, objClass, metadataMap);
  		}
  		else if (FINAL_IMMUTABLE_CLASSES.contains(objClass))
  		{
  			objMap.put(toCopy, toCopy);
  			retval = toCopy;
  		}
  		else
  		{
  			retval = handleObjectWithNoArgsConstructor(metadataMap, objClass, objMap, toCopy);
  		}
  		return retval;
  	}
  
  	private static Object handleObjectWithNoArgsConstructor(final Map metadataMap, final Class
objClass, final Map objMap, final Object toCopy)
  	{
  		final Object retval;
  		ClassMetadata metadata = (ClassMetadata) metadataMap.get(objClass);
  		if (metadata == null)
  		{
  			metadata = new ClassMetadata();
  			metadataMap.put(objClass, metadata);
  		}
  		Constructor noArg = metadata.m_noArgConstructor;
  		if (noArg == null)
  		{
  			try
  			{
  				noArg = objClass.getDeclaredConstructor(EMPTY_CLASS_ARRAY);
  				metadata.m_noArgConstructor = noArg;
  			}
  			catch (Exception e)
  			{
  				throw new ObjectCopyException("class [" + objClass.getName() + "] has no noArg constructor:
" + e.toString(), e);
  			}
  		}
  		if (!metadata.m_noArgConstructorAccessible && (Modifier.PUBLIC & noArg.getModifiers())
== 0)
  		{
  			try
  			{
  				noArg.setAccessible(true);
  			}
  			catch (SecurityException e)
  			{
  				throw new ObjectCopyException("cannot access noArg constructor [" + noArg + "] of class
[" + objClass.getName() + "]: " + e.toString(), e);
  			}
  			metadata.m_noArgConstructorAccessible = true;
  		}
  		try
  		{
  			/**
  			 * create the return value via the default no argument constructor
  			 */
  			retval = noArg.newInstance(EMPTY_OBJECT_ARRAY);
  			objMap.put(toCopy, retval);
  		}
  		catch (Exception e)
  		{
  			throw new ObjectCopyException("cannot instantiate class [" + objClass.getName() + "]
using noArg constructor: " + e.toString(), e);
  		}
  		for (Class c = objClass; c != Object.class; c = c.getSuperclass())
  		{
  			copyClass(metadataMap, c, toCopy, retval, objMap);
  		}
  		return retval;
  	}
  
  	private static void copyClass(final Map metadataMap, final Class c, final Object obj, final
Object retval, final Map objMap)
  	{
  		ClassMetadata metadata;
  		metadata = (ClassMetadata) metadataMap.get(c);
  		if (metadata == null)
  		{
  			metadata = new ClassMetadata();
  			metadataMap.put(c, metadata);
  		}
  		Field[] declaredFields = metadata.m_declaredFields;
  		if (declaredFields == null)
  		{
  			declaredFields = c.getDeclaredFields();
  			metadata.m_declaredFields = declaredFields;
  		}
  		setFields(obj, retval, declaredFields, metadata.m_fieldsAccessible, objMap, metadataMap);
  		metadata.m_fieldsAccessible = true;
  	}
  
  	private static Object handleArray(final Object obj, final Map objMap, final Class objClass,
final Map metadataMap)
  	{
  		final Object retval;
  		final int arrayLength = Array.getLength(obj);
  		/**
  		 * immutable
  		 */
  		if (arrayLength == 0)
  		{
  			objMap.put(obj, obj);
  			retval = obj;
  		}
  		else
  		{
  			final Class componentType = objClass.getComponentType();
  			/**
  			 * even though arrays implicitly have a public clone(), it
  			 * cannot be invoked reflectively, so need to do copy construction
  			 */
  			retval = Array.newInstance(componentType, arrayLength);
  			objMap.put(obj, retval);
  			if (componentType.isPrimitive() || FINAL_IMMUTABLE_CLASSES.contains(componentType))
  			{
  				System.arraycopy(obj, 0, retval, 0, arrayLength);
  			}
  			else
  			{
  				for (int i = 0; i < arrayLength; ++i)
  				{
  					/**
  					 * recursively clone each array slot:
  					 */
  					final Object slot = Array.get(obj, i);
  					if (slot != null)
  					{
  						final Object slotClone = clone(slot, objMap, metadataMap);
  						Array.set(retval, i, slotClone);
  					}
  				}
  			}
  		}
  		return retval;
  	}
  
  	/**
  	 * copy all fields from the "from" object to the "to" object.
  	 *
  	 * @param from source object
  	 * @param to from's clone
  	 * @param fields fields to be populated
  	 * @param accessible 'true' if all 'fields' have been made accessible during
  	 * traversal
  	 */
  	private static void setFields(final Object from, final Object to,
  								  final Field[] fields, final boolean accessible,
  								  final Map objMap, final Map metadataMap)
  	{
  		for (int f = 0, fieldsLength = fields.length; f < fieldsLength; ++f)
  		{
  			final Field field = fields[f];
  			final int modifiers = field.getModifiers();
  			if ((Modifier.STATIC & modifiers) != 0) continue;
  			if ((Modifier.FINAL & modifiers) != 0)
  				throw new ObjectCopyException("cannot set final field [" + field.getName() + "] of class
[" + from.getClass().getName() + "]");
  			if (!accessible && ((Modifier.PUBLIC & modifiers) == 0))
  			{
  				try
  				{
  					field.setAccessible(true);
  				}
  				catch (SecurityException e)
  				{
  					throw new ObjectCopyException("cannot access field [" + field.getName() + "] of class
[" + from.getClass().getName() + "]: " + e.toString(), e);
  				}
  			}
  			try
  			{
  				cloneAndSetFieldValue(field, from, to, objMap, metadataMap);
  			}
  			catch (Exception e)
  			{
  				throw new ObjectCopyException("cannot set field [" + field.getName() + "] of class ["
+ from.getClass().getName() + "]: " + e.toString(), e);
  			}
  		}
  	}
  
  	private static void cloneAndSetFieldValue(final Field field, final Object src, final Object
dest, final Map objMap, final Map metadataMap) throws IllegalAccessException
  	{
  		Object value = field.get(src);
  		if (value == null)
  		{
  			/**
  			 *  null is a valid type, ie the object may initialize this field to a different value,
  			 * so we must explicitely set all null fields.
  			 */
  			field.set(dest, null);
  		}
  		else
  		{
  			final Class valueType = value.getClass();
  			if (!valueType.isPrimitive() && !FINAL_IMMUTABLE_CLASSES.contains(valueType))
  			{
  				/**
  				 * recursively call clone on value as it could be an object reference, an array,
  				 * or some mutable type
  				 */
  				value = clone(value, objMap, metadataMap);
  			}
  			field.set(dest, value);
  		}
  	}
  }
  
  
  
  1.14      +2 -2      db-ojb/src/java/org/apache/ojb/otm/core/BaseConnection.java
  
  Index: BaseConnection.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/core/BaseConnection.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- BaseConnection.java	1 Jul 2003 21:04:56 -0000	1.13
  +++ BaseConnection.java	7 Jul 2003 22:54:15 -0000	1.14
  @@ -187,7 +187,7 @@
               if (lock != LockType.WRITE_LOCK)
               {
                   copyStrategy = _tx.getKit().getCopyStrategy(oid);
  -                object = copyStrategy.copy(object);
  +                object = copyStrategy.copy(object, _pb.getDescriptorRepository());
               }
           }
   
  @@ -409,7 +409,7 @@
               else if (_lock != LockType.WRITE_LOCK && isMaterialized(object))
               {
                   copyStrategy = _tx.getKit().getCopyStrategy(oid);
  -                object = copyStrategy.copy(object);
  +                object = copyStrategy.copy(object, _pb.getDescriptorRepository());
               }
   
               try
  
  
  

---------------------------------------------------------------------
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