You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by rd...@apache.org on 2003/01/12 17:04:56 UTC

cvs commit: jakarta-commons/beanutils/src/java/org/apache/commons/beanutils DynaProperty.java

rdonkin     2003/01/12 08:04:56

  Modified:    beanutils/src/java/org/apache/commons/beanutils
                        DynaProperty.java
  Log:
  The java 1.3 JVM (I run on) throws a ClassNotFoundException whenever primitive type classes (eg Double.TYPE) are deserialized. This means that DynaProperty serialization often fails. This is a workaround for this problem. The standard serialization mechanism is replaced by a custom implementation which serialization the primitive type classes using ints. I haven't tested it on later JVMs so I'd be grateful if people out there could find the time to update and run the tests on their platform just to ensure i haven't broken things for anyone else.
  
  Revision  Changes    Path
  1.5       +140 -7    jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/DynaProperty.java
  
  Index: DynaProperty.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/DynaProperty.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DynaProperty.java	13 Jul 2002 18:03:39 -0000	1.4
  +++ DynaProperty.java	12 Jan 2003 16:04:56 -0000	1.5
  @@ -63,7 +63,11 @@
   package org.apache.commons.beanutils;
   
   
  +import java.io.IOException;
   import java.io.Serializable;
  +import java.io.ObjectOutputStream;
  +import java.io.ObjectInputStream;
  +import java.io.StreamCorruptedException;
   import java.util.List;
   import java.util.Map;
   
  @@ -77,6 +81,25 @@
   
   public class DynaProperty implements Serializable {
   
  +    // ----------------------------------------------------------- Constants
  +    
  +    /*
  +     * There are issues with serializing primitive class types on certain JVM versions
  +     * (including java 1.3).
  +     * This class uses a custom serialization implementation that writes an integer
  +     * for these primitive class.
  +     * This list of constants are the ones used in serialization.
  +     * If these values are changed, then older versions will no longer be read correctly
  +     */
  +    private static final int BOOLEAN_TYPE = 1;
  +    private static final int BYTE_TYPE = 2;
  +    private static final int CHAR_TYPE = 3;
  +    private static final int DOUBLE_TYPE = 4;
  +    private static final int FLOAT_TYPE = 5;
  +    private static final int INT_TYPE = 6;
  +    private static final int LONG_TYPE = 7;
  +    private static final int SHORT_TYPE = 8;
  +    
   
       // ----------------------------------------------------------- Constructors
   
  @@ -122,10 +145,16 @@
   
   
       /**
  -     * The Java class representing the data type of the underlying property
  -     * values.
  +     * <p>The Java class representing the data type of the underlying property
  +     * values.</p>
  +     * 
  +     * <p>There are issues with serializing primitive class types on certain JVM versions
  +     * (including java 1.3).
  +     * Therefore, this field <strong>must not be serialized using the standard methods</strong>.</p>
  +     * 
  +     * <p><strong>Please leave this field as <code>transient</code></strong></p>
        */
  -    protected Class type = null;
  +    protected transient Class type = null;
   
       public Class getType() {
           return (this.type);
  @@ -181,5 +210,109 @@
   
       }
   
  +    // --------------------------------------------------------- Serialization helper methods
  +    
  +    /**
  +     * Writes this object safely.
  +     * There are issues with serializing primitive class types on certain JVM versions
  +     * (including java 1.3).
  +     * This method provides a workaround.
  +     */
  +    private void writeObject(ObjectOutputStream out) throws IOException {
  +        // safely write out type class
  +        int primitiveType = 0;
  +        if (Boolean.TYPE.equals(type)) {
  +            primitiveType = BOOLEAN_TYPE;
  +        } else if (Byte.TYPE.equals(type)) {
  +            primitiveType = BYTE_TYPE;
  +        } else if (Character.TYPE.equals(type)) {
  +            primitiveType = CHAR_TYPE;
  +        } else if (Double.TYPE.equals(type)) {
  +            primitiveType = DOUBLE_TYPE;
  +        } else if (Float.TYPE.equals(type)) {
  +            primitiveType = FLOAT_TYPE;
  +        } else if (Integer.TYPE.equals(type)) {
  +            primitiveType = INT_TYPE;
  +        } else if (Long.TYPE.equals(type)) {
  +            primitiveType = LONG_TYPE;
  +        } else if (Short.TYPE.equals(type)) {
  +            primitiveType = SHORT_TYPE;
  +        }	
  +        
  +        if (primitiveType == 0) {
  +            // then it's not a primitive type
  +            out.writeBoolean(false);
  +            out.writeObject(type);
  +        } else {
  +            // we'll write out a constant instead
  +            out.writeBoolean(true);
  +            out.writeInt(primitiveType);
  +        }
  +        
  +        // write out other values
  +        out.defaultWriteObject();
  +    }
  +    
  +    /**
  +     * Reads field values for this object safely.
  +     * There are issues with serializing primitive class types on certain JVM versions
  +     * (including java 1.3).
  +     * This method provides a workaround.
  +     *
  +     * @throws StreamCorruptedException when the stream data values are outside expected range 
  +     */
  +    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
  +        // read back type class safely 
  +        if (in.readBoolean()) {
  +            // it's a type constant
  +            switch (in.readInt()) {
  +            
  +                case BOOLEAN_TYPE:
  +                    type = Boolean.TYPE;
  +                    break;
  +                    
  +                case BYTE_TYPE:
  +                    type = Byte.TYPE;
  +                    break;
  +                
  +                case CHAR_TYPE:
  +                    type = Character.TYPE;
  +                    break;
  +                
  +                case DOUBLE_TYPE:
  +                    type = Double.TYPE;
  +                    break;
  +                
  +                case FLOAT_TYPE:
  +                    type = Float.TYPE;
  +                    break;
  +                
  +                case INT_TYPE:
  +                    type = Integer.TYPE;
  +                    break;
  +                
  +                case LONG_TYPE:
  +                    type = Long.TYPE;
  +                    break;
  +                
  +                case SHORT_TYPE:
  +                    type = Short.TYPE;
  +                    break;
  +                
  +                default:
  +                    // something's gone wrong
  +                    throw new StreamCorruptedException(
  +                        "Invalid primitive type. "
  +                        + "Check version of beanutils used to serialize is compatible.");
   
  +            }
  +              
  +        } else {
  +            // it's another class
  +            type = (Class) in.readObject();
  +        }
  +        
  +        // read other values
  +        in.defaultReadObject();
  +    }
   }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>