Package org.apache.axis.encoding

Source Code of org.apache.axis.encoding.Deserializer

/*
* 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 org.apache.axis.Constants;

import org.apache.axis.message.EnvelopeHandler;
import org.apache.axis.message.MessageElement;
import org.apache.axis.message.SAX2EventRecorder;
import org.apache.axis.message.SAXOutputter;
import org.apache.axis.message.SOAPHandler;
import org.apache.axis.utils.JavaUtils;
import org.apache.log4j.Category;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

import javax.xml.rpc.namespace.QName;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Vector;

/** The Deserializer base class.
*
* Still needs some work.
*
* @author Glen Daniels (gdaniels@allaire.com)
*/

public class Deserializer extends SOAPHandler
{
    static Category category =
            Category.getInstance(Deserializer.class.getName());

    protected Object value = null;
    //protected DeserializationContext context = null;
    protected boolean isComplete = false;

    protected Vector targets = null;
   
    public Object getValue()
    {
        return value;
    }
    public void setValue(Object value)
    {
        this.value = value;
    }

    /////////////////////////////////////////////////////////////
    //  Reflection-based insertion of values into target objects
    //  once deserialization is complete.
    //
    public interface Target {
        public void set(Object value) throws SAXException;

    }

    public static class FieldTarget implements Target {
        private Object targetObject;
        private Field targetField;

        public FieldTarget(Object targetObject, Field targetField)
        {
            this.targetObject = targetObject;
            this.targetField = targetField;
        }
       
        public FieldTarget(Object targetObject, String fieldName)
            throws NoSuchFieldException
        {
            Class cls = targetObject.getClass();
            targetField = cls.getField(fieldName);
            this.targetObject = targetObject;
        }

        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);
            }
        }
    }
   
    public static class MethodTarget implements Target {
        private Object targetObject;
        private Method targetMethod;
        private static final Class [] objArg = new Class [] { Object.class };

        public MethodTarget(Object targetObject, String methodName)
            throws NoSuchMethodException
        {
            this.targetObject = targetObject;
            Class cls = targetObject.getClass();
            targetMethod = cls.getMethod(methodName, objArg);
        }
       
        public void set(Object value) throws SAXException {
            try {
                targetMethod.invoke(targetObject, new Object [] { value });
            } catch (IllegalAccessException accEx) {
                accEx.printStackTrace();
                throw new SAXException(accEx);
            } catch (IllegalArgumentException argEx) {
                argEx.printStackTrace();
                throw new SAXException(argEx);
            } catch (InvocationTargetException targetEx) {
                targetEx.printStackTrace();
                throw new SAXException(targetEx);
            }
        }
    }

    class CallbackTarget implements Target {
        public ValueReceiver target;
        public Object hint;
        CallbackTarget(ValueReceiver target, Object hint)
        {
            this.target = target;
            this.hint = hint;
        }
       
        public void set(Object value) throws SAXException {
            target.valueReady(value, hint);
        }
    }

    public void registerCallback(ValueReceiver target, Object hint)
    {
        if (target == null)
            return;
       
        registerValueTarget(new CallbackTarget(target, hint));
    }
   

    public void registerValueTarget(Target target)
    {
        if (targets == null)
            targets = new Vector();
       
        targets.addElement(target);
    }
   
    public void registerValueTarget(Object target, String fieldName)
        throws NoSuchFieldException
    {
        registerValueTarget(new FieldTarget(target, fieldName));
    }
   
    /** Add someone else's targets to our own (see DeserializationContext)
     *
     */
    public void copyValueTargets(Deserializer other)
    {
        if ((other == null) || (other.targets == null))
            return;
       
        if (targets == null)
            targets = new Vector();
       
        Enumeration e = other.targets.elements();
        while (e.hasMoreElements()) {
            targets.addElement(e.nextElement());
        }
    }
   
    /**
     * Store the value into the target
     */
    public void valueComplete() throws SAXException
    {
        isComplete = true;
       
        if (targets != null) {
            Enumeration e = targets.elements();
            while (e.hasMoreElements()) {
                Target target = (Target)e.nextElement();
                target.set(value);
                if (category.isDebugEnabled()) {
                    category.debug(JavaUtils.getMessage("setValueInTarget00",
                            "" + value, "" + target));
                }
            }
        }
    }
   
    private int startIdx = 0;
    private int endIdx = -1;
    private boolean isHref = false;
   
    /** Subclasses override this
     */
    public void onStartElement(String namespace, String localName,
                             String qName, Attributes attributes,
                             DeserializationContext context)
        throws SAXException
    {
        // If I'm the base class, try replacing myself with an
        // appropriate deserializer gleaned from type info.
        if (this.getClass().equals(Deserializer.class)) {
            QName type = context.getTypeFromAttributes(namespace,
                                                       localName,
                                                       attributes);
           
            if (category.isDebugEnabled()) {
                category.debug(JavaUtils.getMessage("gotType00", "Deser", "" + type));
            }
           
            // We know we're deserializing, and we can't seem to figure
            // out a type... so let's give them a string.
            // ??? Is this the right thing to do?
            if (type != null) {
                Deserializer dser =
                                   context.getTypeMappingRegistry().getDeserializer(type);
                if (dser != null) {
                    dser.copyValueTargets(this);
                    context.replaceElementHandler(dser);
                    // And don't forget to give it the start event...
                    dser.startElement(namespace, localName, qName,
                                      attributes, context);
                }
            } else {
                startIdx = context.getCurrentRecordPos();
            }
        }
    }
   
    public SOAPHandler onStartChild(String namespace, String localName,
                             String prefix, Attributes attributes,
                             DeserializationContext context)
        throws SAXException
    {
        return null;
    }
   
    public void startElement(String namespace, String localName,
                             String qName, Attributes attributes,
                             DeserializationContext context)
        throws SAXException
    {
        // If the xsi:nil attribute, set the value to null and return since
        // there is nothing to deserialize.
        String nil = null;
        for (int i = 0; i < Constants.URIS_SCHEMA_XSI.length && nil == null; i++)
            nil = attributes.getValue(Constants.URIS_SCHEMA_XSI[i], "nil");
        if (nil != null && nil.equals("true")) {
          value = null;
          return;
        }

        // If this element has an id, then associate the value with the id.
        // (Prior to this association, the MessageElement of the element is
        // associated with the id. Failure to replace the MessageElement at this
        // point will cause an infinite loop during deserialization if the
        // current element contains child elements that cause an href back to this id.)
        // Also note that that endElement() method is responsible for the final
        // assoication of this id with the completed value.
        String id = attributes.getValue("id");
        if (id != null) {
            context.addObjectById(id, value);
            if (category.isDebugEnabled()) {
                category.debug("Initiali put of deserialized value=" + value + " for id= "+ id);
            }    
        }

        String href = attributes.getValue("href");
        if (href != null) {
            isHref = true;
           
            Object ref = context.getObjectByRef(href);
           
            if (category.isDebugEnabled()) {
                category.debug(JavaUtils.getMessage(
                        "gotForID00",
                        new String[] {"" + ref, href, "" + ref.getClass()}));
            }
           
            if (ref == null) {
                // Nothing yet... register for later interest.
                context.registerFixup(href, this);
            }
           
            if (ref instanceof MessageElement) {
                /*
                if (this.getClass().equals(Deserializer.class)) {
                    QName type = ((MessageElement)ref).getType();
                    Deserializer dser =
                                   context.getTypeMappingRegistry().getDeserializer(type);
                    System.out.println("dser = " + dser);
                    if (dser != null) {
                        dser.copyValueTargets(this);
                        context.replaceElementHandler(dser);
                    }
                }
                */
                context.replaceElementHandler(new EnvelopeHandler(this));

                SAX2EventRecorder r = context.recorder;
                context.recorder = null;
                ((MessageElement)ref).publishToHandler(context);
                context.recorder = r;
            } else {
                // If the ref is not a MessageElement, then it must be an
                // element that has already been deserialized.  Use it directly.
                value = ref;
            }
           
            // !!! INSERT DEALING WITH ATTACHMENTS STUFF HERE?
        } else {
            isHref = false;
            onStartElement(namespace, localName, qName, attributes,
                           context);
        }
    }
   
    /**
     * Subclasses override this to do custom functionality at the
     * end of their enclosing element.  This will NOT be called
     * for HREFs...
     *
     */
    public void onEndElement(String namespace, String localName,
                           DeserializationContext context)
        throws SAXException
    {
        // If we only have SAX events, but someone really wanted a
        // value, try sending them the contents of this element
        // as a String...
        // ??? Is this the right thing to do here?
       
        if (this.getClass().equals(Deserializer.class) &&
            targets != null &&
            !targets.isEmpty()) {
            endIdx = context.getCurrentRecordPos();
           
            StringWriter writer = new StringWriter();
            SerializationContext serContext =
                        new SerializationContext(writer,
                                                 context.getMessageContext());
            serContext.setSendDecl(false);
            SAXOutputter so = new SAXOutputter(serContext);
            context.curElement.publishContents(so);
           
            value = writer.getBuffer().toString();
        }
    }
   
    public final void endElement(String namespace, String localName,
                           DeserializationContext context)
        throws SAXException
    {
        if (!isHref) {
            onEndElement(namespace, localName, context);
            // !!! It would be nice if we could put the valueComplete()
            // in here, so that it doesn't get called multiple times per
            // multi-ref object, but that's problematic right now.  If
            // a bean containing an array is serialized like this:
            //
            // <bean>
            //  <array href="#1"/>
            // </bean>
            // <multiRef id="1" sOAP-ENC:arrayType="xsd:string[2]">
            //  <item href="#2"/>
            //  <item href="#3"/>
            // </multiRef>
            // <multiRef id="2">Hi there!</multiRef>
            // <multiRef id="3">Hi again</multiRef>
            //
            // ... we'll end up setting the bean's array field at the
            // end of the first <multiRef> element (the array), which
            // will at that point have null values, since the items
            // have yet to be deserialized.  Then when the items get
            // processed (2nd + 3rd multiRefs), the values make it into
            // the Vector inside the ArraySerializer, but not into the
            // bean's array field....
            //
            // The solution to this might be to have each object know
            // when it's "done" (i.e. all array elements are set), and
            // let it call valueComplete() itself.  Though really this is
            // only a problem with objects that we convert (i.e. arrays
            // at the moment), because if no conversion occurs, the
            // values for the later multiRefs just drop into the existing
            // object in place.
        }
        if (value != null)
            valueComplete();

        // If this element has an id, then associate the value with the id.
        // Subsequent hrefs to the id will obtain the value directly.
        // This is necessary for proper multi-reference deserialization.
        if (context.curElement != null) {
            String id = context.curElement.getAttributeValue("id");
            if (id != null) {
                context.addObjectById(id, value);
                if (category.isDebugEnabled()) {
                    category.debug("Put deserialized value=" + value + " for id= "+ id);
                }    
            }
        }
    }
}
TOP

Related Classes of org.apache.axis.encoding.Deserializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.