fi.iki.murgo.irssinotifier.Server.java Source code

Java tutorial

Introduction

Here is the source code for fi.iki.murgo.irssinotifier.Server.java

Source

package fi.iki.murgo.irssinotifier;

import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;

import android.accounts.Account;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie2;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import android.util.Log;

public class Server {
    private static final String TAG = Server.class.getName();

    private final Preferences preferences;
    private final Activity activity;

    private boolean usingDevServer = false; // must be false when deploying

    public enum ServerTarget {
        SaveSettings, Test, FetchData, Authenticate, Message, WipeSettings, GetNonce, License,
    }

    private Map<ServerTarget, String> serverUrls = new HashMap<ServerTarget, String>();

    private DefaultHttpClient http_client = new DefaultHttpClient();

    private static final int maxRetryCount = 2;

    public Server(Activity activity) {
        this.activity = activity;
        this.preferences = new Preferences(activity);
        String baseServerUrl = "https://irssinotifier.appspot.com";

        if (usingDevServer) {
            baseServerUrl = "http://10.0.2.2:8080";
        }

        serverUrls.put(ServerTarget.SaveSettings, baseServerUrl + "/API/Settings");
        serverUrls.put(ServerTarget.WipeSettings, baseServerUrl + "/API/Wipe");
        serverUrls.put(ServerTarget.Message, baseServerUrl + "/API/Message");
        serverUrls.put(ServerTarget.Authenticate, baseServerUrl + "/_ah/login?continue=https://localhost/&auth=");
        serverUrls.put(ServerTarget.GetNonce, baseServerUrl + "/API/Nonce");
        serverUrls.put(ServerTarget.License, baseServerUrl + "/API/License");
    }

    public boolean authenticate() throws IOException {
        return authenticate(0);
    }

    private boolean authenticate(int retryCount) throws IOException {
        if (usingDevServer) {
            BasicClientCookie2 cookie = new BasicClientCookie2("dev_appserver_login",
                    "irssinotifier@gmail.com:False:118887942201532232498");
            cookie.setDomain("10.0.2.2");
            cookie.setPath("/");
            http_client.getCookieStore().addCookie(cookie);

            return true;
        }

        String token = preferences.getAuthToken();
        try {
            if (token == null) {
                String accountName = preferences.getAccountName();
                if (accountName == null) {
                    return false;
                }

                token = generateToken(accountName);
                preferences.setAuthToken(token);
            }

            boolean success = doAuthenticate(token);
            if (success) {
                Log.v(TAG, "Succesfully logged in.");
                return true;
            }
        } catch (IOException e) {
            throw e;
        } catch (Exception e) {
            Log.e(TAG, "Unable to send settings: " + e.toString());
            e.printStackTrace();
            preferences.setAccountName(null); // reset because authentication or unforeseen error
            return false;
        }

        Log.w(TAG, "Login failed, retrying... Retry count " + (retryCount + 1));
        http_client = new DefaultHttpClient();
        preferences.setAuthToken(null);

        if (retryCount >= maxRetryCount) {
            preferences.setAccountName(null); // reset because it's not accepted by the server
            return false;
        }

        return authenticate(retryCount + 1);
    }

    private String generateToken(String accountName)
            throws OperationCanceledException, AuthenticatorException, IOException {
        UserHelper uf = new UserHelper();
        return uf.getAuthToken(activity, new Account(accountName, UserHelper.ACCOUNT_TYPE));
    }

    private boolean doAuthenticate(String token) throws IOException {
        if (checkCookie())
            return true;

        try {
            Log.v(TAG, "Authenticating...");

            // Don't follow redirects
            http_client.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false);

            HttpGet http_get = new HttpGet(serverUrls.get(ServerTarget.Authenticate) + token);
            HttpResponse response;
            response = http_client.execute(http_get);

            EntityUtils.toString(response.getEntity()); // read response to prevent warning
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 302) {
                Log.w(TAG, "No redirect, login failed. Status code: " + statusCode);
                return false;
            } else {
                Log.v(TAG, "Redirected, OK. Status code: " + statusCode);
            }

            return checkCookie();
        } finally {
            if (http_client != null)
                http_client.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, true);
        }
    }

    private boolean checkCookie() {
        for (Cookie c : http_client.getCookieStore().getCookies()) {
            if (c.getName().equals("SACSID")) {
                Log.v(TAG, "Found SACSID cookie");
                if (!c.isExpired(new Date())) {
                    return true;
                } else {
                    Log.w(TAG, "SACSID cookie expired");
                }
            }
        }

        Log.w(TAG, "No valid SACSID cookie found");
        http_client.getCookieStore().clear();
        return false;
    }

    public ServerResponse post(MessageToServer message, ServerTarget target) throws IOException {
        HttpPost httpPost = new HttpPost(serverUrls.get(target));
        httpPost.setEntity(new StringEntity(message.getHttpString()));

        HttpResponse response = http_client.execute(httpPost);
        int statusCode = response.getStatusLine().getStatusCode();
        String responseString = EntityUtils.toString(response.getEntity());

        ServerResponse serverResponse;
        serverResponse = new ServerResponse(statusCode, responseString);

        if (serverResponse.wasSuccesful()) {
            Log.i(TAG, "Settings sent to server");
        } else {
            Log.e(TAG, "Unable to send settings! Response status code: " + statusCode + ", response string: "
                    + responseString);
        }

        return serverResponse;
    }

    public ServerResponse get(MessageToServer message, ServerTarget target) throws IOException {
        String url = serverUrls.get(target);
        url = buildUrlWithParameters(url, message.getMap());
        HttpGet httpGet = new HttpGet(url);

        HttpResponse response = http_client.execute(httpGet);
        int statusCode = response.getStatusLine().getStatusCode();
        String responseString = EntityUtils.toString(response.getEntity());

        ServerResponse serverResponse;
        if (target == ServerTarget.Message)
            serverResponse = new MessageServerResponse(statusCode, responseString);
        else
            serverResponse = new ServerResponse(statusCode, responseString);

        if (serverResponse.wasSuccesful()) {
            Log.i(TAG, "Data fetched from server, target type " + target);
        } else {
            Log.e(TAG, "Unable to fetch data from server! Response status code: " + statusCode
                    + ", response string: " + responseString);
        }

        return serverResponse;
    }

    private static String buildUrlWithParameters(String url, Map<String, String> parameters) {
        if (!url.endsWith("?"))
            url += "?";

        List<NameValuePair> params = new ArrayList<NameValuePair>();

        for (Entry<String, String> entry : parameters.entrySet()) {
            params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }

        String paramString = URLEncodedUtils.format(params, "utf-8");

        url += paramString;
        return url;
    }

}