org.accada.reader.rp.proxy.Result.java Source code

Java tutorial

Introduction

Here is the source code for org.accada.reader.rp.proxy.Result.java

Source

/*
 * Copyright (C) 2007 ETH Zurich
 *
 * This file is part of Accada (www.accada.org).
 *
 * Accada is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software Foundation.
 *
 * Accada 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 Accada; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301  USA
 */

package org.accada.reader.rp.proxy;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.net.URL;

import org.accada.reader.rp.proxy.msg.Handshake;
import org.accada.reader.rp.proxy.util.ResourceLocator;
import org.accada.reader.rprm.core.msg.Context;
import org.accada.reader.rprm.core.msg.MessageFactory;
import org.accada.reader.rprm.core.msg.MessageFormat;
import org.accada.reader.rprm.core.msg.MessageParser;
import org.accada.reader.rprm.core.msg.MessageParsingException;
import org.accada.reader.rprm.core.msg.MessagingConstants;
import org.accada.reader.rprm.core.msg.reply.Reply;
import org.accada.reader.rprm.core.msg.transport.HttpMessageHeaderParser;
import org.accada.reader.rprm.core.msg.transport.TcpMessageHeaderParser;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.Logger;

/**
 * This class listen to the the ProxyConnection and parse and process result messages from reader.
 * If the result message will not be received within the timeout time, a error will be created.
 * 
 * @author regli
 */
public class Result {

    /** the logger */
    private static final Logger LOG = Logger.getLogger(Result.class);

    /** path to the properties file */
    private static final String PROPERTIES_FILE = "/props/RPProxy.xml";
    private static final String DEFAULT_PROPERTIES_FILE = "/props/RPProxy_default.xml";

    /** the handshake stores message format and transport protocol */
    private final Handshake handshake;

    /** contains the header data of the result message */
    private StringBuffer header = new StringBuffer();

    /** contains the body data of the result message */
    private StringBuffer body = new StringBuffer();

    /** indicates if the end of the header is reached */
    private boolean isHeaderFragment = true;

    /** stores the length of the message body */
    private int bodyLength = -1;

    /** the parsed reply message */
    private Reply reply = null;

    /** indicates if the whole message is already parsed */
    private boolean complete = false;

    /** stores the error if message parsing fail */
    private MessageParsingException error;

    /** time in ms, the result waits max for a return message */
    private int timeout;

    /**
     * Constructor set handshake and load timeout from properties file.
     * 
     * @param handshake stores message format and transport protocol
     */
    public Result(Handshake handshake) {

        this.handshake = handshake;

        XMLConfiguration conf;
        URL fileurl = ResourceLocator.getURL(PROPERTIES_FILE, DEFAULT_PROPERTIES_FILE, this.getClass());
        try {
            conf = new XMLConfiguration(fileurl);
            timeout = conf.getInt("timeout");
        } catch (Exception e) {
            timeout = 60000;
            LOG.warn("Invalid property file '" + PROPERTIES_FILE + "'. Timeout set to 60 000 ms");
        }

    }

    /**
     * This method adds a new message fragment to the result message.
     * 
     * @param fragment message fragment
     * @throws IOException if fragment could not be read properly
     */
    public synchronized void addMsgFragment(String fragment) throws IOException {

        if (isHeaderFragment) {
            if (handshake.getTransportProtocol() == Handshake.HTTP) {
                processHttpHeaderFragment(fragment);
            } else if (handshake.getTransportProtocol() == Handshake.TCP) {
                processTcpHeaderFragment(fragment);
            }
        } else {
            processBodyFragment(fragment);
        }

    }

    /**
     * this method initializes the result.
     */
    public synchronized void init() {

        header = new StringBuffer();
        body = new StringBuffer();
        isHeaderFragment = true;
        bodyLength = -1;
        complete = false;
        reply = null;

    }

    /**
     * This method returns the reply.
     * 
     * @return reply
     */
    public synchronized Reply get() {

        int counter = 0;
        while (complete == false && counter < timeout / 100) {
            counter++;
            try {
                wait(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return reply;

    }

    /**
     * This method returns the header.
     * 
     * @return header
     */
    public synchronized String getHeader() {

        return header.toString();

    }

    /**
     * This method returns the body.
     * 
     * @return body
     */
    public synchronized String getBody() {

        return body.toString();

    }

    /**
     * This method returns the error code.
     * 
     * @return error code
     */
    public synchronized int getErrorCode() {

        int counter = 0;
        while (complete == false && counter < timeout / 100) {
            counter++;
            try {
                wait(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return counter >= timeout / 100 ? 55555 : reply == null ? error.getResultCode() : reply.getResultCode();

    }

    /**
     * This method returns the error name.
     * 
     * @return error name
     */
    public synchronized String getErrorName() {

        int counter = 0;
        while (complete == false && counter < timeout / 100) {
            counter++;
            try {
                wait(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return counter >= timeout / 100 ? "No Reply available after " + (timeout / 1000) + "s."
                : reply == null ? error.getErrorName() : reply.getError().getName();

    }

    /**
     * This method returns the error description.
     * 
     * @return error description
     */
    public synchronized String getErrorDescription() {

        int counter = 0;
        while (complete == false && counter < timeout / 100) {
            counter++;
            try {
                wait(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return counter >= timeout / 100 ? "No Reply available after  " + (timeout / 1000) + "s."
                : reply == null ? error.getErrorDescription() : reply.getError().getDescription();

    }

    //
    // private methods
    //

    /**
     * This method processes a http message header fragment.
     * 
     * @param fragment http message header fragment
     * @throws IOException if the http message header fragment could not be processed properly
     */
    private void processHttpHeaderFragment(String fragment) throws IOException {

        int eolPos = fragment.indexOf(MessagingConstants.EOL);
        if (eolPos > -1) {
            if (eolPos == 0 && header.toString().endsWith(MessagingConstants.EOL)) {
                header.append(MessagingConstants.EOL);
                parseHttpHeader();
                processBodyFragment(fragment.substring(MessagingConstants.EOL.length()));
            } else {
                int lastEolPos;
                do {
                    lastEolPos = eolPos;
                    eolPos = fragment.indexOf(MessagingConstants.EOL, lastEolPos + 1);
                } while (eolPos > -1 && eolPos - lastEolPos > MessagingConstants.EOL.length());
                if (eolPos > -1) {
                    header.append(fragment.substring(0, eolPos + MessagingConstants.EOL.length()));
                    parseHttpHeader();
                    processBodyFragment(fragment.substring(eolPos + MessagingConstants.EOL.length()));
                } else {
                    header.append(fragment);
                }
            }
        } else {
            header.append(fragment);
        }

    }

    /**
     * This method processes a tcp message header fragment.
     * 
     * @param fragment tcp message header fragment
     * @throws IOException if the tcp message header fragment could not be processed properly
     */
    private void processTcpHeaderFragment(String fragment) throws IOException {

        int eohPos = fragment.indexOf(MessagingConstants.EOH);
        if (eohPos > -1) {
            header.append(fragment.substring(0, eohPos + MessagingConstants.EOH.length()));
            parseTcpHeader();
            processBodyFragment(fragment.substring(eohPos + MessagingConstants.EOH.length()));
        } else {
            header.append(fragment);
        }

    }

    /**
     * This method processes a message body fragment.
     * 
     * @param fragment message body fragment
     */
    private void processBodyFragment(String fragment) {

        body.append(fragment);
        if (body.length() >= bodyLength) {
            parseBody();
        }

    }

    /**
     * This method parses the http header.
     * 
     * @throws IOException if the http header could not be parsed properly
     */
    private void parseHttpHeader() throws IOException {

        isHeaderFragment = false;
        bodyLength = HttpMessageHeaderParser.readHandshake(new BufferedReader(new StringReader(header.toString())))
                .getContentLength();

    }

    /**
     * This method parses the tcp message header.
     * 
     * @throws IOException if the tcp message header could not be parsed properly
     */
    private void parseTcpHeader() throws IOException {

        isHeaderFragment = false;
        bodyLength = TcpMessageHeaderParser
                .readTcpMessageHeader(new BufferedReader(new StringReader(header.toString()))).getLength();

    }

    /**
     * This method parses the message body.
     */
    private void parseBody() {

        MessageFormat format;
        if (handshake.getMessageFormat() == Handshake.FORMAT_XML) {
            format = MessageFormat.XML;
        } else {
            format = MessageFormat.TEXT;
        }
        MessageFactory messageFactory = new MessageFactory();
        try {
            MessageParser parser = messageFactory.createParser(format, Context.REPLY);
            reply = (Reply) parser.parseReplyMessage(body.toString());
        } catch (MessageParsingException e) {
            error = e;
        }
        complete = true;

    }

}