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

org.ow2.petals.binding.rest.exchange.HTTPHelper Maven / Gradle / Ivy

/**
 * Copyright (c) 2007-2012 EBM WebSourcing, 2012-2020 Linagora
 * 
 * This program/library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * This program/library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program/library; If not, see http://www.gnu.org/licenses/
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.binding.rest.exchange;

import java.io.IOException;
import java.io.OutputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jbi.messaging.Fault;
import javax.jbi.messaging.MessagingException;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;

import org.apache.http.entity.ContentType;
import org.eclipse.jetty.http.HttpStatus;
import org.glassfish.jersey.message.internal.AcceptableMediaType;
import org.glassfish.jersey.message.internal.HttpHeaderReader;

import com.ebmwebsourcing.easycommons.xml.SourceHelper;

public final class HTTPHelper {

    private static Collection XML_MEDIATYPES;

    private static Collection JSON_MEDIATYPES;

    private static Collection ACCEPTED_MEDIATYPES;

    static {
        // note: for all of these, order is important and they should not be wildcard types!
        XML_MEDIATYPES = new ArrayList<>();
        // we put application/xml first
        XML_MEDIATYPES.add(MediaType.APPLICATION_XML_TYPE);
        XML_MEDIATYPES.add(MediaType.TEXT_XML_TYPE);
        XML_MEDIATYPES.add(MediaType.APPLICATION_ATOM_XML_TYPE);
        XML_MEDIATYPES.add(MediaType.APPLICATION_SVG_XML_TYPE);
        XML_MEDIATYPES.add(MediaType.APPLICATION_XHTML_XML_TYPE);

        JSON_MEDIATYPES = new ArrayList<>();
        JSON_MEDIATYPES.add(MediaType.APPLICATION_JSON_TYPE);

        ACCEPTED_MEDIATYPES = new ArrayList<>();
        // we put JSON types first
        ACCEPTED_MEDIATYPES.addAll(JSON_MEDIATYPES);
        ACCEPTED_MEDIATYPES.addAll(XML_MEDIATYPES);
    }

    private HTTPHelper() {
        // Utility class --> No constructor
    }

    public static boolean isOkStatus(final int httpStatus) {
        return 200 <= httpStatus && httpStatus < 300;
    }

    public static boolean isXMLMediaType(final ContentType contentType) {
        return isXMLMediaType(toMediaType(contentType));
    }

    public static MediaType compatible(final MediaType mt, final Collection mts) {
        for (MediaType m : mts) {
            if (mt.isCompatible(m)) {
                return m;
            }
        }
        return null;
    }

    /**
     * Check if the specified media type is a XML media type
     * 
     * @param mediaType
     *            a media type
     * @return true if the specified media type is a XML media type, otherwise false
     */
    public static final boolean isXMLMediaType(final MediaType mediaType) {
        return mediaType != null && compatible(mediaType, XML_MEDIATYPES) != null;
    }

    public static boolean isJSONMediaType(final ContentType contentType) {
        return isJSONMediaType(toMediaType(contentType));
    }

    /**
     * Check if the specified media type is a JSON media type
     * 
     * @param mediaType
     *            a media type
     * @return true if the specified media type is a JSON media type, otherwise false
     */
    public static final boolean isJSONMediaType(final MediaType mediaType) {
        return mediaType != null && compatible(mediaType, JSON_MEDIATYPES) != null;
    }

    /**
     * Check if the specified media type is a multipart media type
     * 
     * @param mediaType
     *            a media type
     * @return true if the specified media type is a multipart media type, otherwise false
     */
    public static final boolean isMultipartMediaType(final MediaType mediaType) {
        return mediaType != null
                && (mediaType.getType().equals(MediaType.MULTIPART_FORM_DATA_TYPE.getType()));
    }

    public static boolean isLoggable(final ContentType contentType) {
        return isLoggable(toMediaType(contentType));
    }

    private static MediaType toMediaType(final ContentType contentType) {
        return contentType == null ? null : MediaType.valueOf(contentType.toString());
    }

    public static boolean isLoggable(final MediaType mediaType) {

        return mediaType != null && (isJSONMediaType(mediaType) || isXMLMediaType(mediaType)
                || mediaType.isCompatible(new MediaType("text", "*")));
    }

    /**
     * Send an HTTP error message
     * 
     * @param logger
     *            the logger
     * @param response
     *            the HTTP response to send
     * @param errorCode
     *            the HTTP code
     * @param errorMessage
     *            an error message
     */
    public static final void sendHTTPErrorResponse(final Logger logger, final HttpServletResponse response,
            final int errorCode, final String errorMessage) {
        try {
            response.sendError(errorCode, errorMessage);
        } catch (IOException io) {
            if (logger.isLoggable(Level.WARNING)) {
                logger.log(Level.WARNING, "Can not send the HTTP error response", io);
            }
        }
    }

    /**
     * Set the response HTTP body
     * 
     * @param msgContentSource
     *            the JBI message content source
     * @param responseConverterFactory
     *            XML to JSON convertion configuration
     * @param output
     *            the output stream associated to the body of the HTTP response in which the XML payload will be written according to selectedMediaType and responseConverterFactory
     * @param selectedMediaType The content type of the HTTP response body
     * 
     * @throws TransformerException
     *             if an unrecoverable error occurs during the course of the transformation
     * @throws IOException
     *             if an I/O error occurs when writing the HTTP body
     * @throws XMLStreamException
     */
    public static void streamHTTPBody(final Source msgContentSource, final XMLOutputFactory responseConverterFactory,
            final OutputStream output, final MediaType selectedMediaType)
            throws TransformerException, IOException, XMLStreamException {

        if (isJSONMediaType(selectedMediaType)) {
            JSONHelper.convertXMLToJSON(msgContentSource, output, responseConverterFactory);
        } else if (isXMLMediaType(selectedMediaType)) {
            output.write(SourceHelper.toByteArray(msgContentSource));
        }
    }
    
    /**
     * Retrieve the content type to use for the HTTP response according to the HTTP request header 'Accept'.
     * 
     * It will return either an XML or a JSON mediatype.
     * 
     * @param acceptHeaderValue
     *            Value of the HTTP request header 'Accept'. Can be {@code null} if no header set.
     * @return The content type to use for HTTP response, or {@code null} if JSON or XML is not accepted.
     */
    public static MediaType findAcceptedMediaType(final String acceptHeaderValue) throws ParseException {
        final List acceptMediaTypes = getResponseContentTypes(acceptHeaderValue);

        // they are ordered by importance
        for (final AcceptableMediaType amt : acceptMediaTypes) {
            // TODO we loose parameters for now, what should we do with them?
            MediaType compatible = compatible(amt, ACCEPTED_MEDIATYPES);
            if (compatible != null) {
                return compatible;
            }
        }

        return null;
    }

    /**
     * @param logger
     *            the logger
     * @param httpResponse
     *            the HTTP response
     * @param fault
     *            the JBI fault
     * @throws TransformerException
     *             if an unrecoverable error occurs during the course of the
     *             transformation
     */
    public static final void sendHTTPErrorResponse(final Logger logger, final HttpServletResponse httpResponse,
            final Fault fault) throws TransformerException {
        final Source source = fault.getContent();
        final String errorMessage;
        if (source == null) {
            errorMessage = "The fault content is empty";
        } else {
            errorMessage = SourceHelper.toString(source);
        }
        sendHTTPErrorResponse(logger, httpResponse, HttpStatus.INTERNAL_SERVER_ERROR_500,
                errorMessage);
    }

    /**
     * Build a list of accepted content type from the given header value
     * 
     * @param acceptHeaderValue
     *            Value of the HTTP Header 'Accept'
     * @return List of accepted content types contained into the HTTP Header value. Not {@link null}.
     * @throws ParseException
     */
    private static final List getResponseContentTypes(final String acceptHeaderValue)
            throws ParseException {
        final List acceptedMediaTypes = acceptHeaderValue == null ? null
                : HttpHeaderReader.readAcceptMediaType(acceptHeaderValue);

        if (acceptedMediaTypes == null || acceptedMediaTypes.isEmpty()) {
            return Collections.singletonList(AcceptableMediaType.valueOf(MediaType.WILDCARD_TYPE));
        }

        return acceptedMediaTypes;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy