All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.org.retep.xmpp.jaxb.XMPPMarshaller Maven / Gradle / Ivy

The newest version!
package uk.org.retep.xmpp.jaxb;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;
import org.w3c.dom.Node;
import uk.org.retep.util.xml.JAXBUtil;
import uk.org.retep.xmpp.message.BaseXMPPMessage;

/**
 * Inner class used by {@link #getJAXBUtil(java.lang.Object)}
 */
public class XMPPMarshaller
{

    private ConcurrentMap packages = new ConcurrentHashMap();

    /**
     * The singleton instance
     * @return singleton
     */
    public static XMPPMarshaller getInstance()
    {
        return Holder.getInstance();
    }

    private int hashCode( final BaseXMPPMessage msg )
    {
        int h = 7;
        h = 79 * h + (msg.getClass().hashCode());
        for( Object child : msg.getContent() )
        {
            h = 79 * h + (child.getClass().hashCode());
        }
        return h;
    }

    private synchronized JAXBUtil createJaxb( final int key,
                                              final BaseXMPPMessage msg )
    {
        JAXBUtil jaxbUtil = packages.get( key );
        if( jaxbUtil == null )
        {
            jaxbUtil = new JAXBUtil();
            jaxbUtil.setClassLoader( msg.getClass().getClassLoader() );
            jaxbUtil.addPackage( msg.getClass() );

            for( Object child : msg.getContent() )
            {
                if( !(child instanceof JAXBElement) )
                {
                    jaxbUtil.addPackage( child.getClass() );
                }
            }

            jaxbUtil.setMarshallerCallback( new JAXBUtil.MarshallerCallback()
            {

                @Override
                public void initialiseMarshaller( final Marshaller marshaller,
                                                  final JAXBUtil jaxbUtil )
                        throws PropertyException
                {
                    // Remove unwanted namespaces from the output
                    //marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
                    marshaller.setProperty(
                            "com.sun.xml.bind.namespacePrefixMapper",
                                            new XMPPNamespacePrefixMapper() );
                    // Always marshall as fragments
                    marshaller.setProperty( "jaxb.fragment", Boolean.TRUE );
                    marshaller.setProperty( "jaxb.formatted.output",
                                            Boolean.TRUE );
                }
            } );

            packages.put( key, jaxbUtil );
        }

        return jaxbUtil;
    }

    public JAXBUtil getJaxbUtil( final BaseXMPPMessage msg )
    {
        final int key = hashCode( msg );
        JAXBUtil jaxbUtil = packages.get( key );
        if( jaxbUtil == null )
        {
            jaxbUtil = createJaxb( key, msg );
        }
        return jaxbUtil;
    }

    public String marshall( final BaseXMPPMessage msg )
            throws JAXBException
    {
        return getJaxbUtil( msg ).marshall( msg );
    }

    public void marshall( final BaseXMPPMessage msg, final Node node )
            throws JAXBException
    {
        getJaxbUtil( msg ).marshall( msg, node );
    }

    /**
     * Holder pattern to lazy initialise the singleton as instantiation is
     * pretty expensive due to the number of packages involved.
     */
    private static class Holder
    {

        private static final XMPPMarshaller instance = new XMPPMarshaller();

        private Holder()
        {
        }

        static XMPPMarshaller getInstance()
        {
            return instance;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy