You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by ru...@apache.org on 2001/05/07 04:20:59 UTC

cvs commit: xml-axis/java/src/org/apache/axis/encoding BeanSerializer.java DeserializerBase.java

rubys       01/05/06 19:20:59

  Modified:    java/samples/echo SOAPStruct.java TestClient.java
               java/src/org/apache/axis/encoding DeserializerBase.java
  Added:       java/src/org/apache/axis/encoding BeanSerializer.java
  Removed:     java/samples/echo SOAPStructSer.java
  Log:
  Add a BeanDeserializer
  
  Note: Reflection already handles primitive types.
  
  Revision  Changes    Path
  1.2       +1 -2      xml-axis/java/samples/echo/SOAPStruct.java
  
  Index: SOAPStruct.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/samples/echo/SOAPStruct.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SOAPStruct.java	2001/05/06 03:09:18	1.1
  +++ SOAPStruct.java	2001/05/07 02:20:58	1.2
  @@ -64,8 +64,7 @@
   
       // items of the structure.  Defined as Objects so as to permit nulls
       // Note: these need to be public in order to be directly set by the
  -    // deserializer.  Bean accessors are also provided for a potential
  -    // future BeanDeserializer.
  +    // deserializer.
       public Integer varInt;
       public String varString;
       public Float varFloat;
  
  
  
  1.3       +6 -3      xml-axis/java/samples/echo/TestClient.java
  
  Index: TestClient.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/samples/echo/TestClient.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- TestClient.java	2001/05/06 21:00:48	1.2
  +++ TestClient.java	2001/05/07 02:20:58	1.3
  @@ -56,8 +56,11 @@
   package samples.echo ;
   
   import java.lang.reflect.Array;
  +import java.util.Hashtable;
  +
   import org.apache.axis.AxisFault ;
   import org.apache.axis.client.HTTPCall ;
  +import org.apache.axis.encoding.BeanSerializer;
   import org.apache.axis.encoding.SOAPTypeMappingRegistry;
   import org.apache.axis.encoding.ServiceDescription;
   import org.apache.axis.encoding.TypeMappingRegistry;
  @@ -132,9 +135,9 @@
   
           // register the SOAPStruct class
           QName ssqn = new QName("http://soapinterop.org/xsd", "SOAPStruct");
  -        call.addSerializer(SOAPStruct.class, ssqn, new SOAPStructSer());
  -        call.addDeserializerFactory(ssqn, SOAPStruct.class,
  -                                    SOAPStructSer.getFactory());
  +        Class cls = SOAPStruct.class;
  +        call.addSerializer(cls, ssqn, new BeanSerializer(cls));
  +        call.addDeserializerFactory(ssqn, cls, BeanSerializer.getFactory(cls));
   
           // execute the tests
           test("echoString", "abcdefg");
  
  
  
  1.7       +30 -27    xml-axis/java/src/org/apache/axis/encoding/DeserializerBase.java
  
  Index: DeserializerBase.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/DeserializerBase.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- DeserializerBase.java	2001/05/06 15:57:20	1.6
  +++ DeserializerBase.java	2001/05/07 02:20:58	1.7
  @@ -112,29 +112,41 @@
       //  Reflection-based insertion of values into target objects
       //  once deserialization is complete.
       //
  -    //  !!! This needs to be expanded to deal with accessor methods
  -    //      (i.e. Beans) as well, not to mention primitive types.
  -    //
  -    //
  -    class FieldTarget {
  -        public Object targetObject;
  -        public Field targetField;
  +    interface Target {
  +        public void set(Object value) throws SAXException;
  +
  +    }
  +
  +    class FieldTarget implements Target {
  +        private Object targetObject;
  +        private Field targetField;
  +
           public FieldTarget(Object targetObject, Field targetField)
           {
               this.targetObject = targetObject;
               this.targetField = targetField;
           }
  +
  +        public void set(Object value) throws SAXException {
  +            try {
  +                targetField.set(targetObject, value);
  +            } catch (IllegalAccessException accEx) {
  +                accEx.printStackTrace();
  +                throw new SAXException(accEx);
  +            } catch (IllegalArgumentException argEx) {
  +                argEx.printStackTrace();
  +                throw new SAXException(argEx);
  +            }
  +        }
       }
  +
       protected Vector targets = null;
  -    public void registerValueTarget(Object target, Field field)
  +    public void registerValueTarget(Target target)
       {
  -        if ((target == null) || (field == null))
  -            return;
  -        
           if (targets == null)
               targets = new Vector();
           
  -        targets.addElement(new FieldTarget(target,field));
  +        targets.addElement(target);
       }
       
       public void registerValueTarget(Object target, String fieldName)
  @@ -143,7 +155,8 @@
               Class cls = target.getClass();
               Field field = cls.getField(fieldName);
           
  -            registerValueTarget(target, field);
  +            if (field != null)
  +                registerValueTarget(new FieldTarget(target, field));
           } catch (NoSuchFieldException ex) {
               ex.printStackTrace();
           }
  @@ -163,8 +176,8 @@
           }
       }
       
  -    /** !!! Only works with object values right now.
  -     * TODO: Get primitives working
  +    /** 
  +     * Store the value into the target
        */
       public void valueComplete() throws SAXException
       {
  @@ -181,19 +194,9 @@
           if (targets != null) {
               Enumeration e = targets.elements();
               while (e.hasMoreElements()) {
  -                FieldTarget target = (FieldTarget)e.nextElement();
  -                Field field = target.targetField;
  -                Object object = target.targetObject;
  +                Target target = (Target)e.nextElement();
  +                target.set(value);
                   
  -                try {
  -                    field.set(object, value);
  -                } catch (IllegalAccessException accEx) {
  -                    accEx.printStackTrace();
  -                    throw new SAXException(accEx);
  -                } catch (IllegalArgumentException argEx) {
  -                      argEx.printStackTrace();
  -                      throw new SAXException(argEx);
  -                }
               }
           }
       }
  
  
  
  1.1                  xml-axis/java/src/org/apache/axis/encoding/BeanSerializer.java
  
  Index: BeanSerializer.java
  ===================================================================
  /*
   * 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 "Axis" and "Apache Software Foundation" 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",
   *    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/>.
   */
  
  package org.apache.axis.encoding;
  
  import java.io.IOException;
  import java.util.Hashtable;
  import java.util.Vector;
  
  import java.beans.BeanInfo;
  import java.beans.Introspector;
  import java.beans.PropertyDescriptor;
  
  import org.apache.axis.encoding.*;
  import org.apache.axis.utils.QName;
  
  import org.xml.sax.*;
  
  /**
   * General purpose serializer/deserializerFactory for an arbitrary java bean.
   *
   * @author Sam Ruby <ru...@us.ibm.com>
   */
  public class BeanSerializer extends DeserializerBase implements Serializer {
  
      /**
       * Class being serialized/deserialized
       */
      private Class cls;
  
      /**
       * Property Descriptors.  Retrieved once and cached in the serializer.
       */
      private PropertyDescriptor[] pd;
      
      /**
       * An array of nothing, defined only once.
       */
      private static final Object[] noArgs = new Object[] {};
  
      /**
       * Constructor that takes a class.  Called only for serializers, so it
       * does NOT creates an instance of the bean.
       */
      public BeanSerializer(Class cls) throws Exception {
              if (cls==null) throw new NullPointerException("baz");
          this.cls = cls;
          this.pd = Introspector.getBeanInfo(cls).getPropertyDescriptors();
      }
  
      /**
       * Constructor that takes a class and a pre-computed PropertyDescriptor.
       * Called only for deserializers, so it DOES create an instance.
       */
      public BeanSerializer(Class cls, PropertyDescriptor[] pd) throws Exception {
              if (cls==null) throw new NullPointerException("bar");
          this.cls = cls;
          this.pd = pd;
          this.value = cls.newInstance();
      }
  
      /**
       * BeanSerializer Factory that creates instances with the specified
       * class.  Caches the PropertyDescriptor
       */
      private static class BeanSerFactory implements DeserializerFactory {
          private Class cls;
          private PropertyDescriptor[] pd;
  
          public BeanSerFactory(Class cls) throws Exception{
              this.cls = cls;
              this.pd = Introspector.getBeanInfo(cls).getPropertyDescriptors();
          }
  
          public DeserializerBase getDeserializer() {
              try {
                  return new BeanSerializer(cls, pd);
              } catch (Exception e) {
                  // I'm not allowed to throw much, so I throw what I can!
                  throw new NullPointerException(e.toString());
              }
          }
      }
  
      /**
       * Accessor for the BeanSerializerFactory
       */
      public static DeserializerFactory getFactory(Class cls) throws Exception {
          return new BeanSerFactory(cls);
      }
  
      /**
       * Class which knows how to update a bean property
       */
      class PropertyTarget implements Target {
          private Object object;
          private PropertyDescriptor pd;
  
          public PropertyTarget(Object object, PropertyDescriptor pd) {
              this.object = object;
              this.pd     = pd;
          }
  
          public void set(Object value) throws SAXException {
              try {
                  pd.getWriteMethod().invoke(object, new Object[] {value});
              } catch (Exception e) {
                  throw new SAXException(e);
              }
          }
      }
      
      /** 
       * Deserializer interface called on each child element encountered in
       * the XML stream.
       */
      public void onStartChild(String namespace, String localName,
                               String qName, Attributes attributes)
          throws SAXException
      {
  
          // look for a field by this name.  Assumes the the number of
          // properties in a bean is (relatively) small, so uses a linear
          // search.
          for (int i=0; i<pd.length; i++) {
              if (pd[i].getName().equals(localName)) {
  
                  // determine the QName for this child element
                  TypeMappingRegistry tmr = context.getTypeMappingRegistry();
                  QName qn = tmr.getTypeQName(pd[i].getPropertyType());
                  if (qn == null)
                      throw new SAXException("Unregistered type: " + 
                                             pd[i].getPropertyType());
  
                  // get the deserializer
                  DeserializerBase dSer = context.getDeserializer(qn);
                  if (dSer == null)
                      throw new SAXException("No deserializer for " + 
                                             pd[i].getPropertyType());
  
                  // Success!  Register the target and deserializer.
                  dSer.registerValueTarget(new PropertyTarget(value, pd[i]));
                  context.pushElementHandler(dSer);
                  return;
              }
          }
  
          // No such field
          throw new SAXException("Invalid element in " + cls.getName() +
                                 " - " + localName);
      }
      
      /** 
       * Serialize a bean.  Done simply by serializing each bean property.
       */
      public void serialize(QName name, Attributes attributes,
                            Object value, SerializationContext context)
          throws IOException
      {
          context.startElement(name, attributes);
  
          try {
              for (int i=0; i<pd.length; i++) {
                  String propName = pd[i].getName();
                  if (propName.equals("class")) continue;
                  Object propValue = pd[i].getReadMethod().invoke(value,noArgs);
                  context.serialize(new QName("", propName), null, propValue);
              }
          } catch (Exception e) {
              throw new IOException(e.toString());
          }
  
          context.endElement();
      }
  }