package jianshu.io.app.model;
import android.content.Context;
import android.util.Log;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import net.tsz.afinal.FinalHttp;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.protocol.HttpContext;
import java.util.ArrayList;
import java.util.List;
import jianshu.io.app.util.WebViewCookieParser;
/**
* Created by Administrator on 2014/4/12.
* session_id 每次登陆都会变化
* user_token 对用户来说是唯一不变的
*/
public class JianshuSession {
static final String DOMAIN = "jianshu.io";
private static JianshuSession sInstance;
public static synchronized JianshuSession init(Context context) {
if (sInstance == null) {
sInstance = new JianshuSession(context);
}
return sInstance;
}
public static JianshuSession getsInstance() {
return sInstance;
}
private Context context;
private JianshuSessionState mSessionState;
private FinalHttp mFinalHttpForHtml;
private FinalHttp mFinalHttpForJavaScript;
private String mCookieStr;
private CookieManager mCookieManager;
private List<BasicClientCookie> mCookieList;
private List<JianshuSessionListener> listeners = new ArrayList<JianshuSessionListener>();
private String mUserToken;
private String mSession;
private JianshuSession(Context context) {
this.context = context;
CookieSyncManager.createInstance(context);
mCookieManager = CookieManager.getInstance();
validate();
}
private void createFinalHttp() {
mFinalHttpForJavaScript = new FinalHttp();
initHttp(mFinalHttpForJavaScript);
mFinalHttpForJavaScript.addHeader("Accept", "*/*;q=0.5, text/javascript, application/javascript, application/ecmascript, application/x-ecmascript");
mFinalHttpForHtml = new FinalHttp();
initHttp(mFinalHttpForHtml);
mFinalHttpForHtml.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
}
private void initHttp(FinalHttp http) {
http.addHeader("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.0.3; zh-cn; HTC T328d) AndroidWebKit/534.30 (KHTML, Like Gecko) Version/4.0 Mobile Safari/534.30");
http.addHeader("Accept-Language", "zh-CN, en-US");
http.addHeader("Accept-Charset", "utf-8, iso-8859-1, utf-16, *;q=0.7");
http.getHttpClient().getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);
}
public synchronized void validate() {
String cookieStr = mCookieManager.getCookie(DOMAIN);
if(mCookieStr == null && cookieStr == null) {
setState(new LogoutState());
return;
} else if(mCookieStr != null && cookieStr == null) {
mCookieStr = null;
mCookieList = null;
mUserToken = null;
mSession = null;
setState(new LogoutState());
return;
} else if(mCookieStr != null && mCookieStr.equals(cookieStr)) {
return;
}
mCookieStr = cookieStr;
mCookieList = new WebViewCookieParser().parse(mCookieStr, DOMAIN);
mUserToken = null;
mSession = null;
int breakCount = 0;
for (BasicClientCookie cookie : mCookieList) {
String name = cookie.getName().trim();
if (name.equals("remember_user_token")) {
mUserToken = cookie.getValue();
breakCount++;
} else if (name.equals("_session_id")) {
mSession = cookie.getValue();
breakCount++;
}
if(breakCount == 2) {
break;
}
}
Log.d("jianshu", "user token: " + mUserToken);
Log.d("jianshu", "session: " + mSession);
if (mUserToken != null) {
setState(new LoginState());
} else {
//此时认为该session已经失效了
mSession = null;
setState(new LogoutState());
}
}
public void addListener(JianshuSessionListener listener) {
synchronized (this.listeners) {
this.listeners.add(listener);
}
}
public void removeListener(JianshuSessionListener listener) {
synchronized (this.listeners) {
this.listeners.remove(listener);
}
}
private void onLogin() {
synchronized (listeners) {
for (JianshuSessionListener listener : listeners) {
listener.onLogin();
}
}
}
private void onLogout() {
synchronized (listeners) {
for (JianshuSessionListener listener : listeners) {
listener.onLogout();
}
}
}
public synchronized boolean isUserLogin() {
return getState() instanceof LoginState;
}
private synchronized void setState(JianshuSessionState newState) {
//虽然登陆有可能是换了用户,但是退出的状态就不会是叠加的
if (mSessionState instanceof LogoutState && newState instanceof LogoutState) {
return;
}
mSessionState = newState;
if (this.listeners != null) {
if (newState instanceof LoginState) {
onLogin();
} else {
onLogout();
}
}
}
public synchronized JianshuSessionState getState() {
return mSessionState;
}
public synchronized void notifyUserLogin() {
mSessionState.notifyUserLogin(this);
}
public synchronized void notifyUserLogout() {
mSessionState.notifyUserLogout(this);
}
public synchronized Object getSync(String url, boolean isHtml) {
return mSessionState.getSync(this, url, isHtml);
}
public synchronized Object postSync(String url, boolean isHtml) {
return mSessionState.postSync(this, url, isHtml);
}
public String getUserToken() {
return mUserToken;
}
public String getSession() {
return mSession;
}
abstract class JianshuSessionState {
public abstract void notifyUserLogin(JianshuSession session);
public abstract void notifyUserLogout(JianshuSession session);
public abstract Object getSync(JianshuSession session, String url, boolean isHtml);
public abstract Object postSync(JianshuSession session, String url, boolean isHtml);
}
public class LoginState extends JianshuSessionState {
public LoginState() {
BasicCookieStore cookieStore = new BasicCookieStore();
for (BasicClientCookie cookie : mCookieList) {
cookieStore.addCookie(cookie);
}
createFinalHttp();
HttpContext httpContext;
httpContext = mFinalHttpForJavaScript.getHttpContext();
httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
httpContext = mFinalHttpForHtml.getHttpContext();
httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
}
@Override
public void notifyUserLogin(JianshuSession session) {
validate();
}
@Override
public void notifyUserLogout(JianshuSession session) {
session.setState(new LogoutState());
}
@Override
public Object getSync(JianshuSession session, String url, boolean isHtml) {
FinalHttp finalHttp = isHtml ? mFinalHttpForHtml : mFinalHttpForJavaScript;
return finalHttp.getSync(url);
}
@Override
public Object postSync(JianshuSession session, String url, boolean isHtml) {
FinalHttp finalHttp = isHtml ? mFinalHttpForHtml : mFinalHttpForJavaScript;
return finalHttp.postSync(url);
}
}
public class LogoutState extends JianshuSessionState {
public LogoutState() {
createFinalHttp();
}
@Override
public void notifyUserLogin(JianshuSession session) {
Log.d("jianshu", "Logout notifyUserLogin");
validate();
}
@Override
public void notifyUserLogout(JianshuSession session) {
}
@Override
public Object getSync(JianshuSession session, String url, boolean isHtml) {
FinalHttp finalHttp = isHtml ? mFinalHttpForHtml : mFinalHttpForJavaScript;
return finalHttp.getSync(url);
}
@Override
public Object postSync(JianshuSession session, String url, boolean isHtml) {
FinalHttp finalHttp = isHtml ? mFinalHttpForHtml : mFinalHttpForJavaScript;
return finalHttp.postSync(url);
}
}
public interface JianshuSessionListener {
void onLogin();
void onLogout();
}
}