Package org.nimbustools.messaging.query

Source Code of org.nimbustools.messaging.query.CleanSerializationContext

/*
* Copyright 1999-2009 University of Chicago
*
* Licensed 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.nimbustools.messaging.query;

import org.apache.axis.description.TypeDesc;
import org.apache.axis.message.MessageElement;
import org.apache.axis.encoding.SerializationContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.xml.sax.Attributes;

import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.*;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;

@Provider
@Produces({"text/xml"})
public class AxisBodyWriter implements MessageBodyWriter<Object> {

    private static final Log logger =
            LogFactory.getLog(AxisBodyWriter.class.getName());

    private static final String GET_TYPE_DESC = "getTypeDesc";
    private static final String TYPE_SUFFIX = "Type";

    @Context
    MessageContext messageContext;


    // this is a travesty

    public boolean isWriteable(Class<?> aClass, Type type,
                               Annotation[] annotations, MediaType mediaType) {

        return getTypeDescVerySlowly(aClass) != null;
    }

    public long getSize(Object o, Class aClass, Type type,
                        Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    public void writeTo(Object o, Class aClass, Type type,
                        Annotation[] annotations, MediaType mediaType,
                        MultivaluedMap multivaluedMap,
                        OutputStream outputStream)
            throws IOException, WebApplicationException {
        final TypeDesc typeDesc = getTypeDescVerySlowly(aClass);

        final QName qName = typeDesc.getXmlType();

        if (qName == null) {
            throw new WebApplicationException(500);
        }

        String name = qName.getLocalPart();
        // responses should not have 'Type' on end of element name. ugly.
        if (name.endsWith(TYPE_SUFFIX)) {
            name = name.substring(0, name.length() - TYPE_SUFFIX.length());
        }

        String namespace = getNamespaceUriFromContext();
        if (namespace == null) {
            namespace = qName.getNamespaceURI();
        }

        final OutputStreamWriter writer =
                new OutputStreamWriter(outputStream);

        //manually write the xml header deal
        writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");

        MessageElement element = new MessageElement(name, "", namespace);
        try {
            element.setObjectValue(o);

            final SerializationContext context =
                    new CleanSerializationContext(writer, namespace);
            context.setDoMultiRefs(false);
            context.setPretty(true);
            element.output(context);


        } catch (SOAPException e) {
            throw new WebApplicationException(e);
        } catch (Exception e) {
            throw new WebApplicationException(e);
        }
        writer.close();
    }

    private String getNamespaceUriFromContext() {
        if (this.messageContext != null) {

            final HttpHeaders headers = this.messageContext.getHttpHeaders();
            if (headers != null) {
                final List<String> versionHeaders =
                        headers.getRequestHeader(ElasticQuery.API_VERSION_HEADER);

                if (versionHeaders != null && !versionHeaders.isEmpty()) {
                    final String version = versionHeaders.get(0);
                    if (version.length() > 0) {
                        return "http://ec2.amazonaws.com/doc/" + version + "/";
                    }
                }
            }
        }
        return null;
    }

    private static TypeDesc getTypeDescVerySlowly(Class aClass) {
        try {

            final Method method = aClass.getMethod(GET_TYPE_DESC);
            return (TypeDesc) method.invoke(null);
        } catch (IllegalAccessException e) {
            return null;
        } catch (NoSuchMethodException e) {
            return null;
        } catch (InvocationTargetException e) {
            return null;
        } catch (ClassCastException e) {
            return null;
        }
    }

}

class CleanSerializationContext extends SerializationContext {
    private final String defaultNamespace;

    public CleanSerializationContext(Writer writer, String defaultNamespace) {
        super(writer);
        this.defaultNamespace = defaultNamespace;
    }

    @Override
    public boolean shouldSendXSIType() {
        return false;
    }

    @Override
    public void startElement(QName qName, Attributes attributes) throws IOException {
        // for some reason many of the EC2 types are coming through with an empty namespace
        // override it with the one provided at constructor time
        if ("".equals(qName.getNamespaceURI())) {
            qName = new QName(defaultNamespace, qName.getLocalPart());
        }
        super.startElement(qName, attributes);
    }

    // override these to ensure that by default nil elements are left out of
    // serialized XML. Only the first one is apparently called by MessageElement, but
    // overriding both for completeness.

    @Override
    public void serialize(QName elemQName,
                          Attributes attributes,
                          Object value)
            throws IOException {
        serialize(elemQName, attributes, value, null, Boolean.FALSE, null);
    }

    @Override
    public void serialize(QName elemQName,
                          Attributes attributes,
                          Object value,
                          QName xmlType)
            throws IOException {
        serialize(elemQName, attributes, value, xmlType, Boolean.FALSE, null);
    }
}
TOP

Related Classes of org.nimbustools.messaging.query.CleanSerializationContext

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.