byps.http.HWriteResponseHelper.java Source code

Java tutorial

Introduction

Here is the source code for byps.http.HWriteResponseHelper.java

Source

package byps.http;

/* USE THIS FILE ACCORDING TO THE COPYRIGHT RULES IN LICENSE.TXT WHICH IS PART OF THE SOURCE CODE PACKAGE */
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.ByteBuffer;

import javax.servlet.http.HttpServletResponse;

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

import byps.BBuffer;
import byps.BException;
import byps.BExceptionC;
import byps.BMessageHeader;

public class HWriteResponseHelper {

    private final static Log log = LogFactory.getLog(HWriteResponseHelper.class);
    private HServerListener listener;

    public HWriteResponseHelper(HServerListener listener) {
        this.listener = listener;
    }

    public void writeResponse(ByteBuffer obuf, Throwable e, HttpServletResponse resp, boolean isAsync)
            throws IOException {
        if (log.isDebugEnabled())
            log.debug("writeResponse(" + obuf + ", exception=" + e + ", resp=" + resp);

        if (resp == null) {
            if (log.isDebugEnabled())
                log.debug(")writeResponse timeout");
            return; // timeout
        }

        if (listener != null) {
            if (log.isDebugEnabled())
                log.debug("call onBefore-listener");
            if (listener.onBeforeWriteHttpResponse(obuf, e, resp, isAsync)) {
                if (log.isDebugEnabled())
                    log.debug(")writeResponse, onBefore-listener has written the response.");
            }
        }

        if (e != null) {

            int status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
            if (e instanceof BException) {
                BException bex = (BException) e;
                if (bex.code == BExceptionC.CANCELLED) {
                    status = HttpServletResponse.SC_NOT_ACCEPTABLE;
                } else if (bex.code == BExceptionC.RESEND_LONG_POLL) {
                    status = HttpServletResponse.SC_NO_CONTENT;
                }
            }

            if (status == HttpServletResponse.SC_INTERNAL_SERVER_ERROR) {
                log.warn("Responding server error.", e);
            }

            resp.setStatus(status);

            PrintWriter wr = resp.getWriter();
            String errmsg = e.toString(); // (e instanceof BException) ?
                                          // ((BException)e).msg : e.toString();
            wr.print(errmsg);
            wr.close();

        } else {

            if (log.isDebugEnabled())
                log.debug("copy to servlet output");
            boolean isJson = BMessageHeader.detectProtocol(obuf) == BMessageHeader.MAGIC_JSON;
            resp.setContentType(isJson ? "application/json; charset=UTF-8" : "application/byps");
            resp.setContentLength(obuf.remaining());
            OutputStream os = resp.getOutputStream();

            if (log.isDebugEnabled()) {
                log.debug("buffer: \r\n" + BBuffer.toDetailString(obuf));
            }

            if (isAsync) {

                // Tomcat does not throw an IOException in asynchronous requests, if the
                // client
                // has closed the socket. Somewhere on stackoverflow.com I found a hack
                // to workaround this bug. The workaround splits the message into two
                // parts and calls flush() after each part. The second flush throws the
                // expected exception. But the author of this workaround mentioned, that
                // it does not work in all cases - and I confirm to him.
                // http://stackoverflow.com/questions/7124508/how-to-properly-detect-a-client-disconnect-in-servlet-spec-3
                int pos = obuf.position(), len = obuf.remaining() / 2;
                os.write(obuf.array(), pos, len);
                os.flush();
                os.write(obuf.array(), pos + len, obuf.remaining() - len);
                os.flush();
            } else {
                os.write(obuf.array(), obuf.position(), obuf.remaining());
            }

            os.close();

            if (listener != null) {
                if (log.isDebugEnabled())
                    log.debug("call onAfter-listener");
                listener.onAfterWriteHttpResponse(obuf.remaining());
            }

        }
        if (log.isDebugEnabled())
            log.debug(")writeResponse");
    }

}