com.polyvi.xface.extension.xmlhttprequest.XXMLHttpRequest.java Source code

Java tutorial

Introduction

Here is the source code for com.polyvi.xface.extension.xmlhttprequest.XXMLHttpRequest.java

Source

/*
 Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface)
 This program is distributed under the terms of the GNU General Public License.
    
 This file is part of xFace.
    
 xFace is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
    
 xFace 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 General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with xFace.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.polyvi.xface.extension.xmlhttprequest;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.http.Header;
import org.apache.http.client.HttpResponseException;
import org.apache.http.message.BasicHeader;

import android.content.Context;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;

import com.polyvi.xface.http.XAsyncHttpResponseHandler;
import com.polyvi.xface.http.XHttpWorker;

/**
 * ?W3C ajax
 * 
 */
public class XXMLHttpRequest extends XAsyncHttpResponseHandler implements XIAjaxDataInterface {

    //FIXME:???
    private static final String GET = "GET";
    private static final String POST = "POST";

    private static String[] SupportMethods = { GET, POST };

    /*
              ?                           ??                                        ??
    0       UNSEND               ??, XMLHttpRequest  abort() ?
    1       OPENED               open()
    2       HEADERS_RECEIVED     ??
    3       LOADING              ???
    4       DONE                 ?
      */
    static enum State {
        UNSEND, OPENED, HEADERS_RECEIVED, LOADING, DONE
    }

    private State mState;
    private Map<String, String> mRequestHeaders; // 
    private XHttpWorker mNetWork; //?
    private String mUrl;
    private String mMethod;
    private String mPostData;
    private XAjaxRequestListener mListener;
    private boolean mError;

    private int mHttpStatusCode;// http??
    private String mResponseText; // ?
    private Header[] mResponseHeaders; // ?

    private Context mContext;

    public XXMLHttpRequest(Context context) {
        super();
        mRequestHeaders = new ConcurrentHashMap<String, String>();
        mContext = context;
        mNetWork = new XHttpWorker();
        mResponseText = "";
        mState = State.UNSEND;

    }

    public void open(String method, String url) throws XAjaxException {
        // FIXME: ?????
        if (!isMethodSupported(method)) {
            throw new XAjaxException(XAjaxException.ErrorCode.METHOD_NOT_SUPPORT);
        }
        internalAbort();
        State previouseState = mState;
        mState = State.UNSEND;
        mError = false;
        clearRequest();
        clearResponse();
        if (mState.ordinal() != State.UNSEND.ordinal()) {
            throw new XAjaxException(XAjaxException.ErrorCode.INVALID_STATE_ERR);
        }

        mUrl = url;
        mMethod = method;
        // ?? open?stateReadyChange
        if (previouseState.ordinal() != State.OPENED.ordinal()) {
            this.changeState(State.OPENED);
        } else {
            mState = State.OPENED;
        }

    }

    public void send(String data) throws XAjaxException {
        // FIXME:????
        if (mState != State.OPENED) {
            throw new XAjaxException(XAjaxException.ErrorCode.INVALID_STATE_ERR);
        }

        mPostData = data;
        mError = false;
        doRequest();
    }

    public void setRequestHeader(String name, String value) throws XAjaxException {
        if (mState != State.OPENED) {
            throw new XAjaxException(XAjaxException.ErrorCode.INVALID_STATE_ERR);
        }

        if (!isHeaderValueValid(value)) {
            throw new XAjaxException(XAjaxException.ErrorCode.INVALID_HEADER_VALUE);
        }
        mRequestHeaders.put(name, value);
    }

    /**
     * 
     */
    public void abort() {
        internalAbort();
        clearResponse();
        clearRequest();
        if (mListener != null)
            mListener.onAbort();
        if (mState.ordinal() > State.OPENED.ordinal() && mState.ordinal() != State.DONE.ordinal()) {
            changeState(State.DONE);
        }
        mState = State.UNSEND;

    }

    /**
     * ajax?
     *
     * @param listener
     */
    public void setRequestListener(XAjaxRequestListener listener) {
        mListener = listener;
        if (null != mListener)
            mListener.setAjaxDataInterface(this);
    }

    public XAjaxRequestListener getRequestListener() {
        return mListener;
    }

    /**
     * ?
     * 
     * @param value
     */
    private boolean isHeaderValueValid(String value) {
        return !value.contains("\r") && !value.contains("\n");
    }

    /**
     * ajax??
     * 
     * @param newState
     */
    private void changeState(State newState) {
        if (mState.ordinal() != newState.ordinal()) {
            mState = newState;
            if (null != mListener)
                mListener.onReadyStateChanged();
        }
    }

    /**
     * ?
     */
    private void networkError() {
        clearRequest();
        clearResponse();
        mError = true;

        if (null != mListener)
            mListener.onNetworkError();
        changeState(State.DONE);
        internalAbort();
    }

    /**
     * ??ajax
     * 
     * @return
     * @throws XAjaxException
     */
    private void doRequest() throws XAjaxException {
        addCookie(mUrl);
        if (mMethod.equalsIgnoreCase(GET)) {
            mNetWork.get(mUrl, this.convertHeaders(mRequestHeaders), this);

        } else if (mMethod.equalsIgnoreCase(POST)) {
            try {
                mNetWork.post(mUrl, this.convertHeaders(mRequestHeaders), mPostData, null, this);
            } catch (IOException e) {
                throw new XAjaxException(XAjaxException.ErrorCode.HTTP_REQUEST_ERROR);
            }
        } else {
            throw new XAjaxException(XAjaxException.ErrorCode.METHOD_NOT_SUPPORT);
        }
    }

    /**
     * cookie
     * 
     * @param url
     *            url?
     */
    private void addCookie(String url) {
        // cookie?
        CookieSyncManager cookieSyncManager = CookieSyncManager.createInstance(mContext);
        cookieSyncManager.startSync();
        String cookie = CookieManager.getInstance().getCookie(url);
        if (cookie != null) {
            mRequestHeaders.put("Cookie", cookie);
        }
    }

    /**
     * hash?header[]
     * 
     * @return
     */
    private Header[] convertHeaders(Map<String, String> mapHeaders) {
        Header[] headers = new Header[mapHeaders.size()];
        Iterator<Entry<String, String>> iter = mapHeaders.entrySet().iterator();
        int i = 0;
        while (iter.hasNext()) {
            Entry<String, String> entry = iter.next();
            Header header = new BasicHeader(entry.getKey(), entry.getValue());
            headers[i++] = header;
        }
        return headers;
    }

    /**
     * ?
     */
    private void internalAbort() {
        // ?
        mNetWork.cancelRequest(true);
        mError = true;
    }

    /**
     * 
     */
    private void clearRequest() {
        mRequestHeaders.clear();
        mPostData = null;
        mMethod = null;
        mUrl = null;

    }

    /**
     * ?
     */
    private void clearResponse() {
        mResponseHeaders = null;
        mResponseText = "";
        mHttpStatusCode = 0;
    }

    /**
     * ??
     * 
     * @param name
     * @return
     */
    private boolean isMethodSupported(String name) {
        for (String method : SupportMethods) {
            if (method.equalsIgnoreCase(name)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public int getReadyState() {
        return mState.ordinal();
    }

    @Override
    public int getStatus() {
        return mHttpStatusCode;
    }

    @Override
    public String getResponseText() {
        return mResponseText;
    }

    public String getResponseHeader(String name) {
        if (null == mResponseHeaders)
            return null;
        for (Header header : mResponseHeaders) {
            if (header.getName().equals(name)) {
                return header.getValue();
            }
        }
        return null;
    }

    @Override
    public Header[] getAllResponseHeader() {
        return mResponseHeaders;
    }

    @Override
    public void onSuccess(int statusCode, Header[] headers, String content) {
        // ? ???
        if (mError) {
            return;
        }
        // FIXME:? ?
        this.changeState(State.HEADERS_RECEIVED);
        mHttpStatusCode = statusCode;
        mResponseText = content;
        mResponseHeaders = headers;
        this.changeState(State.LOADING);
        this.changeState(State.DONE);
    }

    @Override
    public void onFailure(Throwable error, String content) {
        // ? ???
        if (mError) {
            return;
        }
        error.printStackTrace();
        if (error instanceof HttpResponseException) {
            mHttpStatusCode = ((HttpResponseException) error).getStatusCode();
        }
        mResponseText = content;
        this.networkError();
    }

}