Java tutorial
/* 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(); } }