org.mule.transport.servlet.AbstractReceiverServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.mule.transport.servlet.AbstractReceiverServlet.java

Source

/*
 * $Id$
 * --------------------------------------------------------------------------------------
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 *
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */

package org.mule.transport.servlet;

import org.mule.RequestContext;
import org.mule.api.MessagingException;
import org.mule.api.MuleContext;
import org.mule.api.MuleMessage;
import org.mule.api.config.MuleProperties;
import org.mule.api.lifecycle.InitialisationException;
import org.mule.api.transformer.TransformerException;
import org.mule.api.transport.OutputHandler;
import org.mule.config.ExceptionHelper;
import org.mule.transport.http.HttpConstants;
import org.mule.transport.http.HttpResponse;
import org.mule.transport.http.transformers.MuleMessageToHttpResponse;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.httpclient.Header;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * A base servlet used to receive requests from a servlet container and route
 * them into Mule
 */

public abstract class AbstractReceiverServlet extends HttpServlet {
    /**
     * logger used by this class
     */
    protected transient Log logger = LogFactory.getLog(getClass());

    public static final String REQUEST_TIMEOUT_PROPERTY = "org.mule.servlet.timeout";
    public static final String FEEDBACK_PROPERTY = "org.mule.servlet.feedback";
    public static final String DEFAULT_CONTENT_TYPE_PROPERTY = "org.mule.servlet.default.content.type";

    /**
     * The name of the servlet connector to use with this Servlet
     * @deprecated Use {@link org.mule.transport.servlet.MuleServletContextListener#CONNECTOR_NAME} instead
     */
    @Deprecated
    public static final String SERVLET_CONNECTOR_NAME_PROPERTY = "org.mule.servlet.connector.name";

    public static final String PAYLOAD_PARAMETER_NAME = "org.mule.servlet.payload.param";
    public static final String DEFAULT_PAYLOAD_PARAMETER_NAME = "payload";

    public static final long DEFAULT_GET_TIMEOUT = 10000L;

    protected String payloadParameterName;
    protected long timeout = DEFAULT_GET_TIMEOUT;
    protected boolean feedback = true;
    protected String defaultContentType = HttpConstants.DEFAULT_CONTENT_TYPE;
    protected MuleContext muleContext;

    private MuleMessageToHttpResponse responseTransformer = new MuleMessageToHttpResponse();

    @Override
    public final void init() throws ServletException {
        String timeoutString = getServletConfig().getInitParameter(REQUEST_TIMEOUT_PROPERTY);
        if (timeoutString != null) {
            timeout = Long.parseLong(timeoutString);
        }
        if (logger.isInfoEnabled()) {
            logger.info("Default request timeout for GET methods is: " + timeout);
        }

        String feedbackString = getServletConfig().getInitParameter(FEEDBACK_PROPERTY);
        if (feedbackString != null) {
            feedback = Boolean.valueOf(feedbackString);
        }
        if (logger.isInfoEnabled()) {
            logger.info("feedback is set to: " + feedback);
        }

        String ct = getServletConfig().getInitParameter(DEFAULT_CONTENT_TYPE_PROPERTY);
        if (ct != null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Using default content type configured on the servlet ("
                        + DEFAULT_CONTENT_TYPE_PROPERTY + ") = " + ct);
            }
            defaultContentType = ct;
        }
        if (logger.isInfoEnabled()) {
            logger.info("Default content type is: " + defaultContentType);
        }

        payloadParameterName = getServletConfig().getInitParameter(PAYLOAD_PARAMETER_NAME);
        if (payloadParameterName == null) {
            payloadParameterName = DEFAULT_PAYLOAD_PARAMETER_NAME;
        }
        if (logger.isInfoEnabled()) {
            logger.info("Using payload param name: " + payloadParameterName);
        }

        muleContext = setupMuleContext();
        setupResponseTransformer();
        doInit();
    }

    protected MuleContext setupMuleContext() throws ServletException {
        MuleContext context = (MuleContext) getServletContext().getAttribute(MuleProperties.MULE_CONTEXT_PROPERTY);
        if (context == null) {
            throw new ServletException(
                    "Property " + MuleProperties.MULE_CONTEXT_PROPERTY + " not set on ServletContext");
        }
        return context;
    }

    protected void setupResponseTransformer() throws ServletException {
        responseTransformer.setMuleContext(muleContext);

        try {
            responseTransformer.initialise();
        } catch (InitialisationException e) {
            throw new ServletException(e);
        }
    }

    protected void doInit() throws ServletException {
        // template method
    }

    protected void writeResponse(HttpServletResponse servletResponse, MuleMessage message) throws Exception {
        if (message == null) {
            writeEmptyResponse(servletResponse);
        } else {
            writeResponseFromMessage(servletResponse, message);
        }
        servletResponse.flushBuffer();
    }

    protected void writeEmptyResponse(HttpServletResponse servletResponse) throws IOException {
        servletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
        if (feedback) {
            servletResponse.setStatus(HttpServletResponse.SC_OK);
            servletResponse.getWriter().write("Action was processed successfully. There was no result");
        }
    }

    protected void writeResponseFromMessage(HttpServletResponse servletResponse, MuleMessage message)
            throws Exception {
        HttpResponse httpResponse = convertToHttpResponse(message);
        setHttpHeadersOnServletResponse(httpResponse, servletResponse);

        if (!servletResponse.isCommitted()) {
            servletResponse.setStatus(httpResponse.getStatusCode());
        }

        if (httpResponse.hasBody()) {
            OutputHandler outputHandler = httpResponse.getBody();
            outputHandler.write(RequestContext.getEvent(), servletResponse.getOutputStream());
        }
    }

    protected HttpResponse convertToHttpResponse(MuleMessage message) throws TransformerException {
        if (message.getPayload() instanceof HttpResponse) {
            return (HttpResponse) message.getPayload();

        } else {
            return (HttpResponse) responseTransformer.transform(message);
        }
    }

    protected HttpServletResponse setHttpHeadersOnServletResponse(HttpResponse httpResponse,
            HttpServletResponse servletResponse) {
        // Remove any Transfer-Encoding headers that were set (e.g. by MuleMessageToHttpResponse)
        // earlier. Mule's default HTTP transformer is used in both cases: when the reply
        // MuleMessage is generated for our standalone HTTP server and for the servlet case. The
        // servlet container should be able to figure out the Transfer-Encoding itself and some
        // get confused by an existing header.
        httpResponse.removeHeaders(HttpConstants.HEADER_TRANSFER_ENCODING);

        Header[] headers = httpResponse.getHeaders();
        for (Header header : headers) {
            servletResponse.addHeader(header.getName(), header.getValue());
        }

        ensureContentTypeHeaderIsSet(servletResponse, httpResponse);

        return servletResponse;
    }

    protected void ensureContentTypeHeaderIsSet(HttpServletResponse servletResponse, HttpResponse httpResponse) {
        Header contentTypeHeader = httpResponse.getFirstHeader(HttpConstants.HEADER_CONTENT_TYPE);
        String contentType = defaultContentType;
        if (contentTypeHeaderIsValid(contentTypeHeader)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Using Content-Type from message header = " + contentTypeHeader.getValue());
            }
            contentType = contentTypeHeader.getValue();
        }
        servletResponse.setContentType(contentType);
    }

    protected boolean contentTypeHeaderIsValid(Header header) {
        return (header != null) && (header.getValue() != null);
    }

    protected void handleException(Throwable exception, String message, HttpServletResponse response) {
        logger.error("message: " + exception.getMessage(), exception);
        int code = Integer.valueOf(ExceptionHelper.getErrorMapping("http", exception.getClass(), muleContext));
        response.setStatus(code);
        try {
            String errorMessage = message + ": " + exception.getMessage();
            if (exception instanceof MessagingException && ((MessagingException) exception).getEvent() != null) {
                MessagingException me = (MessagingException) exception;
                writeErrorResponseFromMessage(response, me.getEvent().getMessage(), code, errorMessage);
            } else {
                response.sendError(code, errorMessage);
            }
        } catch (Exception e) {
            logger.error("Failed to sendError on response: " + e.getMessage(), e);
        }
    }

    protected void writeErrorResponseFromMessage(HttpServletResponse servletResponse, MuleMessage message,
            int errorCode, String errorMessage) throws Exception {
        HttpResponse httpResponse = convertToHttpResponse(message);
        setHttpHeadersOnServletResponse(httpResponse, servletResponse);
        servletResponse.sendError(errorCode, errorMessage);
    }

}