alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Axis 2 example source code file (JAXBBlockImpl.java)

This example Axis 2 source code file (JAXBBlockImpl.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Axis 2 tags/keywords

debug_enabled, debug_enabled, exception, invoking, io, jaxbblockcontext, jaxbelement, jaxbelement, object, object, qname, reflection, security, string, string, text, webserviceexception, xml, xmlstreamwriter

The Axis 2 JAXBBlockImpl.java source code

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.axis2.jaxws.message.databinding.impl;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.MTOMXMLStreamWriter;
import org.apache.axiom.om.util.StAXUtils;
import org.apache.axis2.java.security.AccessController;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.message.Message;
import org.apache.axis2.jaxws.message.attachments.JAXBAttachmentMarshaller;
import org.apache.axis2.jaxws.message.attachments.JAXBAttachmentUnmarshaller;
import org.apache.axis2.jaxws.message.databinding.JAXBBlock;
import org.apache.axis2.jaxws.message.databinding.JAXBBlockContext;
import org.apache.axis2.jaxws.message.databinding.JAXBUtils;
import org.apache.axis2.jaxws.message.databinding.XSDListUtils;
import org.apache.axis2.jaxws.message.factory.BlockFactory;
import org.apache.axis2.jaxws.message.impl.BlockImpl;
import org.apache.axis2.jaxws.utility.XMLRootElementUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.JAXBIntrospector;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.ws.WebServiceException;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.PrivilegedAction;
import java.text.ParseException;

/**
 * JAXBBlockImpl <p/> A Block containing a JAXB business object (either a JAXBElement or an object
 * with @XmlRootElement).
 */
public class JAXBBlockImpl extends BlockImpl implements JAXBBlock {

    private static final Log log = LogFactory.getLog(JAXBBlockImpl.class);

    private static final boolean DEBUG_ENABLED = log.isDebugEnabled();

    /**
     * Called by JAXBBlockFactory
     * 
     * @param busObject..The business object must be a JAXBElement or an object with an
     * @XMLRootElement. This is assertion is validated in the JAXBFactory.
     * @param busContext
     * @param qName QName must be non-null
     * @param factory
     */
    JAXBBlockImpl(Object busObject, JAXBBlockContext busContext, QName qName, 
                  BlockFactory factory)
            throws JAXBException {
        super(busObject, busContext, qName, factory);
    }

    /**
     * Called by JAXBBlockFactory
     * 
     * @param omelement
     * @param busContext
     * @param qName must be non-null
     * @param factory
     */
    JAXBBlockImpl(OMElement omElement, JAXBBlockContext busContext, QName qName,
            BlockFactory factory) {
        super(omElement, busContext, qName, factory);
    }

    @Override
    protected Object _getBOFromReader(XMLStreamReader reader, Object busContext)
        throws XMLStreamException, WebServiceException {
        // Get the JAXBBlockContext. All of the necessry information is recorded on it
        JAXBBlockContext ctx = (JAXBBlockContext) busContext;
        try {
            // TODO Re-evaluate Unmarshall construction w/ MTOM
            Unmarshaller u = JAXBUtils.getJAXBUnmarshaller(ctx.getJAXBContext());

            if (DEBUG_ENABLED) {
                log.debug("Adding JAXBAttachmentUnmarshaller to Unmarshaller");
            }

            Message msg = getParent();

            JAXBAttachmentUnmarshaller aum = new JAXBAttachmentUnmarshaller(msg);
            u.setAttachmentUnmarshaller(aum);

            Object jaxb = null;

            // Unmarshal into the business object.
            if (ctx.getProcessType() == null) {
                jaxb = unmarshalByElement(u, reader); // preferred and always used for
                                                        // style=document
            } else {
                jaxb =
                        unmarshalByType(u,
                                        reader,
                                        ctx.getProcessType(),
                                        ctx.isxmlList(),
                                        ctx.getConstructionType());
            }

            // Successfully unmarshalled the object
            JAXBUtils.releaseJAXBUnmarshaller(ctx.getJAXBContext(), u);
            
            // Don't close the reader.  The reader is owned by the caller, and it
            // may contain other xml instance data (other than this JAXB object)
            // reader.close();
            return jaxb;
        } catch (JAXBException je) {
            if (DEBUG_ENABLED) {
                try {
                    log.debug("JAXBContext for unmarshal failure:" + ctx.getJAXBContext());
                } catch (Exception e) {
                }
            }
            throw ExceptionFactory.makeWebServiceException(je);
        }
    }

    /**
     * @param busObj
     * @param busContext
     * @return
     * @throws XMLStreamException
     * @throws WebServiceException
     */
    private byte[] _getBytesFromBO(Object busObj, Object busContext, String encoding)
        throws XMLStreamException, WebServiceException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        XMLStreamWriter writer = StAXUtils.createXMLStreamWriter(baos, encoding);

        // Since we are writing just the xml,
        // The writer will be a normal writer.
        // All mtom objects will be inlined.
        // writer = new MTOMXMLStreamWriter(writer);

        // Write the business object to the writer
        _outputFromBO(busObj, busContext, writer);

        // Flush the writer
        writer.flush();
        writer.close();
        return baos.toByteArray();
    }


    @Override
    protected XMLStreamReader _getReaderFromBO(Object busObj, Object busContext)
        throws XMLStreamException, WebServiceException {
        ByteArrayInputStream baos =
                new ByteArrayInputStream(_getBytesFromBO(busObj, busContext, "utf-8"));
        return StAXUtils.createXMLStreamReader(baos, "utf-8");
    }

    @Override
    protected void _outputFromBO(Object busObject, Object busContext, XMLStreamWriter writer)
        throws XMLStreamException, WebServiceException {
        JAXBBlockContext ctx = (JAXBBlockContext) busContext;
        try {
            // Very easy, use the Context to get the Marshaller.
            // Use the marshaller to write the object.
            Marshaller m = JAXBUtils.getJAXBMarshaller(ctx.getJAXBContext());


            if (DEBUG_ENABLED) {
                log.debug("Adding JAXBAttachmentMarshaller to Marshaller");
            }

            Message msg = getParent();

            // Pool
            JAXBAttachmentMarshaller am = new JAXBAttachmentMarshaller(msg, writer);
            m.setAttachmentMarshaller(am);


            // Marshal the object
            if (ctx.getProcessType() == null) {
                marshalByElement(busObject, m, writer, !am.isXOPPackage());
            } else {
                marshalByType(busObject,
                              m,
                              writer,
                              ctx.getProcessType(),
                              ctx.isxmlList(),
                              ctx.getConstructionType());
            }

            // Successfully marshalled the data
            JAXBUtils.releaseJAXBMarshaller(ctx.getJAXBContext(), m);
        } catch (JAXBException je) {
            if (DEBUG_ENABLED) {
                try {
                    log.debug("JAXBContext for marshal failure:" + ctx.getJAXBContext());
                } catch (Exception e) {
                }
            }
            throw ExceptionFactory.makeWebServiceException(je);
        }
    }

    /**
     * Get the QName from the jaxb object
     * 
     * @param jaxb
     * @param jbc
     * @throws WebServiceException
     */
    private static QName getQName(Object jaxb, JAXBBlockContext ctx) throws JAXBException {
        JAXBIntrospector jbi = JAXBUtils.getJAXBIntrospector(ctx.getJAXBContext());
        QName qName = jbi.getElementName(jaxb);
        JAXBUtils.releaseJAXBIntrospector(ctx.getJAXBContext(), jbi);
        return qName;
    }

    /**
     * Preferred way to marshal objects.
     * 
     * @param b Object that can be rendered as an element and the element name is known by the
     * Marshaller
     * @param m Marshaller
     * @param writer XMLStreamWriter
     */
    private static void marshalByElement(Object b, Marshaller m, XMLStreamWriter writer,
                                         boolean optimize) throws WebServiceException {
        // Marshalling directly to the output stream is faster than marshalling through the
        // XMLStreamWriter. Take advantage of this optimization if there is an output stream.
        try {
            OutputStream os = (optimize) ? getOutputStream(writer) : null;
            if (os != null) {
                if (DEBUG_ENABLED) {
                    log.debug("Invoking marshalByElement.  Marshaling to an OutputStream. " +
                                "Object is "
                            + getDebugName(b));
                }
                writer.flush();
                m.marshal(b, os);
            } else {
                if (DEBUG_ENABLED) {
                    log.debug("Invoking marshalByElement.  Marshaling to an XMLStreamWriter. " +
                                "Object is "
                            + getDebugName(b));
                }
                m.marshal(b, writer);
            }
        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
    }

    /**
     * Preferred way to unmarshal objects
     * 
     * @param u Unmarshaller
     * @param reader XMLStreamReader
     * @return Object that represents an element
     * @throws WebServiceException
     */
    private static Object unmarshalByElement(final Unmarshaller u, final XMLStreamReader reader)
        throws WebServiceException {
        try {
            if (DEBUG_ENABLED) {
                log.debug("Invoking unMarshalByElement");
            }
            return AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    try {
                        return u.unmarshal(reader);
                    } catch (Exception e) {
                        throw ExceptionFactory.makeWebServiceException(e);
                    }
                }
            });

        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
    }

    /**
     * Marshal objects by type
     * 
     * @param b Object that can be rendered as an element, but the element name is not known to the
     * schema (i.e. rpc)
     * @param m Marshaller
     * @param writer XMLStreamWriter
     * @param type
     */
    private static void marshalByType(final Object b, final Marshaller m,
                                      final XMLStreamWriter writer, final Class type,
                                      final boolean isList, final JAXBUtils.CONSTRUCTION_TYPE ctype)
        throws WebServiceException {
        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                try {

                    // NOTE
                    // Example:
                    // <xsd:simpleType name="LongList">
                    // <xsd:list>
                    // <xsd:simpleType>
                    // <xsd:restriction base="xsd:unsignedInt"/>
                    // </xsd:simpleType>
                    // </xsd:list>
                    // </xsd:simpleType>
                    // <element name="myLong" nillable="true" type="impl:LongList"/>
                    //
                    // LongList will be represented as an int[]
                    // On the wire myLong will be represented as a list of integers
                    // with intervening whitespace
                    // <myLong>1 2 3
                    //
                    // Unfortunately, we are trying to marshal by type. Therefore
                    // we want to marshal an element (foo) that is unknown to schema.
                    // If we use the normal marshal code, the wire will look like
                    // this (which is incorrect):
                    // <foo>123
                    //
                    // The solution is to detect this situation and marshal the
                    // String instead. Then we get the correct wire format:
                    // <foo>1 2 3
                    Object jbo = b;

                    if (isList || (type != null && type.isArray())) {
                        if (DEBUG_ENABLED) {
                            log.debug("marshalling type which is a List or Array");
                        }
                        // We conver to xsdListString only if the type is not known
                        // to the context. In case a jaxbcontext is created from package
                        // the array types or list are not know to the context.
                        if (ctype == JAXBUtils.CONSTRUCTION_TYPE.BY_CONTEXT_PATH) {
                            QName qName = XMLRootElementUtil.getXmlRootElementQNameFromObject(b);
                            String text = XSDListUtils.toXSDListString(getTypeEnabledObject(b));
                            jbo = new JAXBElement(qName, String.class, text);
                        } else if (ctype == JAXBUtils.CONSTRUCTION_TYPE.BY_CLASS_ARRAY) {
                            // do nothing common array types should be know to the jaxbcontext.
                            // so do not use xsdListString conversion.
                        }
                    }

                    // When JAXBContext is created using a context path, it will not include Enum
                    // classes.
                    // These classes have @XmlEnum annotation but not @XmlType/@XmlElement, so the
                    // user will see MarshallingEx, class not known to ctxt.
                    // 
                    // This is a jax-b defect, for now this fix is in place to pass CTS. This only
                    // fixes the
                    // situation where the enum is the top-level object (e.g., message-part in
                    // rpc-lit scenario)
                    //
                    // Sample of what enum looks like:
                    // @XmlEnum public enum EnumString {
                    // @XmlEnumValue("String1") STRING_1("String1"),
                    // @XmlEnumValue("String2") STRING_2("String2");
                    // ... }
                    if (type.isEnum()) {
                        if (b != null) {
                            if (DEBUG_ENABLED) {
                                log.debug("marshalByType. Marshaling " + type.getName()
                                        + " as Enum");
                            }
                            JAXBElement jbe = (JAXBElement) b;
                            String value = XMLRootElementUtil.getEnumValue((Enum) jbe.getValue());

                            jbo = new JAXBElement(jbe.getName(), String.class, value);
                        }
                    }

                    if (DEBUG_ENABLED) {
                        log.debug("Invoking marshalByType.  " +
                                        "Marshaling to an XMLStreamWriter. Object is "
                                + getDebugName(b));
                    }
                    m.marshal(jbo, writer);

                } catch (Exception e) {
                    throw ExceptionFactory.makeWebServiceException(e);
                }
                return null;
            }
        });
    }

    /**
     * The root element being read is defined by schema/JAXB; however its contents are known by
     * schema/JAXB. Therefore we use unmarshal by the declared type (This method is used to
     * unmarshal rpc elements)
     * 
     * @param u Unmarshaller
     * @param reader XMLStreamReader
     * @param type Class
     * @return Object
     * @throws WebServiceException
     */
    private static Object unmarshalByType(final Unmarshaller u, final XMLStreamReader reader,
                                          final Class type, final boolean isList,
                                          final JAXBUtils.CONSTRUCTION_TYPE ctype)
        throws WebServiceException {

        if (DEBUG_ENABLED) {
            log.debug("Invoking unmarshalByType.");
        }

        return AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                try {
                    // Unfortunately RPC is type based. Thus a
                    // declared type must be used to unmarshal the xml.
                    Object jaxb;

                    if (!isList) {
                        // case: We are not unmarshalling an xsd:list but an Array.

                        if (type.isArray()) {
                            // If the context is created using package
                            // we will not have common arrays or type array in the context
                            // so let use a differet way to unmarshal this type
                            if (ctype == JAXBUtils.CONSTRUCTION_TYPE.BY_CONTEXT_PATH) {
                                jaxb = unmarshalAsListOrArray(reader, u, type);
                            }
                            // list on client array on server, Can happen only in start from java
                            // case.
                            else if ((ctype == JAXBUtils.CONSTRUCTION_TYPE.BY_CLASS_ARRAY)) {
                                // The type could be any Object or primitive
                                // I will first unmarshall the xmldata to a String[]
                                // Then use the unmarshalled jaxbElement to create
                                // proper type Object Array.
                                jaxb = u.unmarshal(reader, String[].class);
                                Object typeObj = getTypeEnabledObject(jaxb);
                                // Now convert String Array in to the required Type Array.
                                if (getTypeEnabledObject(typeObj) instanceof String[]) {
                                    String[] strArray = (String[]) typeObj;
                                    String strTokens = new String();
                                    for (String str : strArray) {
                                        strTokens = strTokens + " " + str;
                                    }
                                    QName qName =
                                            XMLRootElementUtil.
                                            getXmlRootElementQNameFromObject(jaxb);
                                    Object obj = XSDListUtils.fromXSDListString(strTokens, type);
                                    jaxb = new JAXBElement(qName, type, obj);
                                }
                            } else {
                                jaxb = u.unmarshal(reader, type);
                            }

                        } else if (type.isEnum()) {
                            // When JAXBContext is created using a context path, it will not 
                            // include Enum classes.
                            // These classes have @XmlEnum annotation but not @XmlType/@XmlElement,
                            // so the user will see MarshallingEx, class not known to ctxt.
                            // 
                            // This is a jax-b defect, for now this fix is in place to pass CTS.
                            // This only fixes the
                            // situation where the enum is the top-level object (e.g., message-part
                            // in rpc-lit scenario)
                            //
                            // Sample of what enum looks like:
                            // @XmlEnum public enum EnumString {
                            // @XmlEnumValue("String1") STRING_1("String1"),
                            // @XmlEnumValue("String2") STRING_2("String2");
                            //
                            // public static getValue(String){} <-- resolves a "value" to an emum
                            // object
                            // ... }
                            if (DEBUG_ENABLED) {
                                log.debug("unmarshalByType. Unmarshalling " + type.getName()
                                        + " as Enum");
                            }

                            JAXBElement<String> enumValue = u.unmarshal(reader, String.class);

                            if (enumValue != null) {
                                Method m =
                                        type.getMethod("fromValue", new Class[] { String.class });
                                jaxb = m.invoke(null, new Object[] { enumValue.getValue() });
                            } else {
                                jaxb = null;
                            }
                        }
                        //Normal case: We are not unmarshalling a xsd:list or Array
                        else {
                            jaxb = u.unmarshal(reader, type);
                        }

                    } else {
                        // If this is an xsd:list, we need to return the appropriate
                        // list or array (see NOTE above)
                        // First unmarshal as a String
                        //Second convert the String into a list or array
                        jaxb = unmarshalAsListOrArray(reader, u, type);
                    }
                    return jaxb;
                } catch (Exception e) {
                    throw ExceptionFactory.makeWebServiceException(e);
                }
            }
        });
    }

    /**
     * convert the String into a list or array
     * @param <T>
     * @param jaxb
     * @param type
     * @return
     * @throws IllegalAccessException
     * @throws ParseException
     * @throws NoSuchMethodException
     * @throws InstantiationException
     * @throws DatatypeConfigurationException
     * @throws InvocationTargetException
     */
    private static Object unmarshalAsListOrArray(XMLStreamReader reader, Unmarshaller u, 
                                                 Class type)
        throws IllegalAccessException, ParseException,NoSuchMethodException,InstantiationException,
        DatatypeConfigurationException,InvocationTargetException,JAXBException {
        //If this is an xsd:list, we need to return the appropriate
        // list or array (see NOTE above)
        // First unmarshal as a String
        Object jaxb = u.unmarshal(reader, String.class);
        //Second convert the String into a list or array
        if (getTypeEnabledObject(jaxb) instanceof String) {
            QName qName = XMLRootElementUtil.getXmlRootElementQNameFromObject(jaxb);
            Object obj = XSDListUtils.fromXSDListString((String) getTypeEnabledObject(jaxb), type);
            return new JAXBElement(qName, type, obj);
        } else {
            return jaxb;
        }

    }


    public boolean isElementData() {
        return true;
    }

    /**
     * Return type enabled object
     *
     * @param obj type or element enabled object
     * @return type enabled object
     */
    static Object getTypeEnabledObject(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof JAXBElement) {
            return ((JAXBElement) obj).getValue();
        }
        return obj;
    }

    private static String getDebugName(Object o) {
        return (o == null) ? "null" : o.getClass().getCanonicalName();
    }

    /**
     * If the writer is backed by an OutputStream, then return the OutputStream
     * @param writer
     * @return OutputStream or null
     */
    private static OutputStream getOutputStream(XMLStreamWriter writer) throws XMLStreamException {
        if (writer.getClass() == MTOMXMLStreamWriter.class) {
            return ((MTOMXMLStreamWriter) writer).getOutputStream();
        }
        return null;
    }
}

Other Axis 2 examples (source code examples)

Here is a short list of links related to this Axis 2 JAXBBlockImpl.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.