Android Open Source - ghwatch Remote System Client






From Project

Back to project page ghwatch.

License

The source code is released under:

Apache License

If you think the Android project ghwatch listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2014 contributors as indicated by the @authors tag.
 * //from ww w.  j  a v a  2  s.  c  o m
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daskiworks.ghwatch.backend;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InvalidObjectException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.NoRouteToHostException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;

import com.daskiworks.ghwatch.Utils;
import com.daskiworks.ghwatch.model.GHCredentials;

/**
 * Helper class used to communicate with server.
 * 
 * @author Vlastimil Elias <vlastimil.elias@worldonline.cz>
 */
public class RemoteSystemClient {

  public static class Response<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    // we do not store data on disc, only statistics values
    public transient T data;

    public boolean notModified = false;
    public Long poolInterval;
    public String lastModified;
    public String rateLimit;
    public String rateLimitRemaining;
    public Long rateLimitReset;

    public long requestStartTime;
    public long requestStopTime;
    public long requestDuration;

    protected void snapRequestDuration() {
      requestStopTime = System.currentTimeMillis();
      requestDuration = requestStopTime - requestStartTime;
    }

    public void fill(Response<?> r2) {
      r2.notModified = notModified;
      r2.poolInterval = poolInterval;
      r2.lastModified = lastModified;
      r2.rateLimit = rateLimit;
      r2.rateLimitRemaining = rateLimitRemaining;
      r2.rateLimitReset = rateLimitReset;
      r2.requestDuration = requestDuration;
      r2.requestStartTime = requestStartTime;
      r2.requestStopTime = requestStopTime;
    }
  }

  private static final String TAG = "RemoteSystemClient";

  /**
   * Get JSON array from specified url. It is contained in <code>list</code> item of output JSO
   * 
   * @param context used to access services
   * @param url to load data from
   * @return JSON array object
   * @throws NoRouteToHostException if internet connection is not available
   * @throws AuthenticationException if authentication fails
   * @throws IOException if there is problem during data readig from server
   * @throws JSONException if returned JSON is invalid
   * @throws URISyntaxException if url is invalid
   */
  public static Response<JSONArray> getJSONArrayFromUrl(Context context, GHCredentials apiCredentials, String url, Map<String, String> headers)
      throws NoRouteToHostException, AuthenticationException, IOException, JSONException, URISyntaxException {
    Response<String> wr = readInternetDataGet(context, apiCredentials, url, headers);
    Response<JSONArray> ret = new Response<JSONArray>();
    wr.fill(ret);
    if (!wr.notModified) {
      ret.data = new JSONArray(wr.data);
    }
    return ret;
  }

  /**
   * Get JSON object from specified url. It is contained in <code>list</code> item of output JSO
   * 
   * @param context used to get services over
   * @param url to load data from
   * @return JSON object
   * @throws NoRouteToHostException if internet connection is not available
   * @throws AuthenticationException if authentication fails
   * @throws IOException if there is problem during data readig from server
   * @throws JSONException if returned JSON is invalid
   * @throws URISyntaxException if url is invalid
   */
  public static Response<JSONObject> getJSONObjectFromUrl(Context context, GHCredentials apiCredentials, String url, Map<String, String> headers)
      throws NoRouteToHostException, AuthenticationException, IOException, JSONException, URISyntaxException {
    Response<String> wr = readInternetDataGet(context, apiCredentials, url, headers);
    Response<JSONObject> ret = new Response<JSONObject>();
    wr.fill(ret);
    if (!wr.notModified) {
      ret.data = new JSONObject(wr.data);
    }
    return ret;
  }

  private static Response<String> readInternetDataGet(Context context, GHCredentials apiCredentials, String url, Map<String, String> headers)
      throws NoRouteToHostException, URISyntaxException, IOException, ClientProtocolException, AuthenticationException, UnsupportedEncodingException {
    if (!Utils.isInternetConnectionAvailable(context))
      throw new NoRouteToHostException("Network not available");

    URI uri = new URI(url);
    DefaultHttpClient httpClient = prepareHttpClient(uri, apiCredentials);

    HttpGet httpGet = new HttpGet(uri);

    setHeaders(httpGet, headers);

    // create response object here to measure request duration
    Response<String> ret = new Response<String>();
    ret.requestStartTime = System.currentTimeMillis();

    HttpResponse httpResponse = httpClient.execute(httpGet);
    int code = httpResponse.getStatusLine().getStatusCode();

    parseResponseHeaders(context, httpResponse, ret);
    Log.d(TAG, "Response http code: " + code);
    if (code == HttpStatus.SC_NOT_MODIFIED) {
      ret.notModified = true;
      ret.snapRequestDuration();
      writeReponseInfo(ret, context);
      return ret;
    }
    processStandardHttpResponseCodes(httpResponse);

    ret.data = getResponseContentAsString(httpResponse);
    ret.snapRequestDuration();
    writeReponseInfo(ret, context);
    return ret;

  }

  protected static String getResponseContentAsString(HttpResponse httpResponse) throws IOException, UnsupportedEncodingException {
    if (httpResponse == null)
      return null;
    HttpEntity httpEntity = httpResponse.getEntity();
    if (httpEntity != null) {
      InputStream is = httpEntity.getContent();
      try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"), 50);
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = reader.readLine()) != null) {
          sb.append(line + "\n");
        }
        return sb.toString();
      } finally {
        if (is != null)
          is.close();
      }
    } else {
      return null;
    }
  }

  protected static void setHeaders(HttpRequestBase httpRequest, Map<String, String> headers) {
    httpRequest.setHeader("User-Agent", "GH::watch");
    if (headers != null) {
      for (Entry<String, String> he : headers.entrySet()) {
        Log.d(TAG, "Set request header " + he.getKey() + ":" + he.getValue());
        httpRequest.setHeader(he.getKey(), he.getValue());
      }
    }
  }

  public static Response<?> postNoData(Context context, GHCredentials apiCredentials, String url, Map<String, String> headers) throws NoRouteToHostException,
      URISyntaxException, IOException, ClientProtocolException, AuthenticationException, UnsupportedEncodingException {
    if (!Utils.isInternetConnectionAvailable(context))
      throw new NoRouteToHostException("Network not available");

    URI uri = new URI(url);
    DefaultHttpClient httpClient = prepareHttpClient(uri, apiCredentials);

    HttpPost httpPost = new HttpPost(uri);

    setHeaders(httpPost, headers);

    // create response object here to measure request duration
    Response<String> ret = new Response<String>();
    ret.requestStartTime = System.currentTimeMillis();

    HttpResponse httpResponse = httpClient.execute(httpPost);
    parseResponseHeaders(context, httpResponse, ret);

    processStandardHttpResponseCodes(httpResponse);

    ret.snapRequestDuration();
    writeReponseInfo(ret, context);
    return ret;
  }

  public static Response<String> putToURL(Context context, GHCredentials apiCredentials, String url, Map<String, String> headers, String content)
      throws NoRouteToHostException, URISyntaxException, IOException, ClientProtocolException, AuthenticationException {
    if (!Utils.isInternetConnectionAvailable(context))
      throw new NoRouteToHostException("Network not available");

    URI uri = new URI(url);
    DefaultHttpClient httpClient = prepareHttpClient(uri, apiCredentials);

    HttpPut httpPut = new HttpPut(uri);

    setHeaders(httpPut, headers);

    if (content != null)
      httpPut.setEntity(new StringEntity(content, "UTF-8"));

    // create response object here to measure request duration
    Response<String> ret = new Response<String>();
    ret.requestStartTime = System.currentTimeMillis();

    HttpResponse httpResponse = httpClient.execute(httpPut);

    parseResponseHeaders(context, httpResponse, ret);

    processStandardHttpResponseCodes(httpResponse);

    ret.data = getResponseContentAsString(httpResponse);

    ret.snapRequestDuration();
    writeReponseInfo(ret, context);
    return ret;
  }

  public static Response<String> deleteToURL(Context context, GHCredentials apiCredentials, String url, Map<String, String> headers)
      throws NoRouteToHostException, URISyntaxException, IOException, ClientProtocolException, AuthenticationException {
    if (!Utils.isInternetConnectionAvailable(context))
      throw new NoRouteToHostException("Network not available");

    URI uri = new URI(url);
    DefaultHttpClient httpClient = prepareHttpClient(uri, apiCredentials);

    HttpDelete httpPut = new HttpDelete(uri);

    setHeaders(httpPut, headers);

    // create response object here to measure request duration
    Response<String> ret = new Response<String>();
    ret.requestStartTime = System.currentTimeMillis();

    HttpResponse httpResponse = httpClient.execute(httpPut);

    parseResponseHeaders(context, httpResponse, ret);

    processStandardHttpResponseCodes(httpResponse);

    ret.data = getResponseContentAsString(httpResponse);

    ret.snapRequestDuration();
    writeReponseInfo(ret, context);
    return ret;
  }

  protected static void processStandardHttpResponseCodes(HttpResponse httpResponse) throws AuthenticationException, IOException {
    int code = httpResponse.getStatusLine().getStatusCode();
    Log.d(TAG, "Response http code: " + code);
    if (code >= 200 && code <= 299)
      return;
    if (code == HttpStatus.SC_UNAUTHORIZED || code == HttpStatus.SC_FORBIDDEN) {
      String OTP = getHeaderValue(httpResponse.getFirstHeader("X-GitHub-OTP"));
      if (code == HttpStatus.SC_UNAUTHORIZED && OTP != null && OTP.contains("required")) {
        throw new OTPAuthenticationException(Utils.trimToNull(OTP.replace("required;", "")));
      }
      throw new AuthenticationException("Authentication problem: " + getResponseContentAsString(httpResponse));
    } else if (code == HttpStatus.SC_BAD_REQUEST || code == HttpStatus.SC_NOT_FOUND) {
      throw new InvalidObjectException("HttpCode=" + code + " message: " + getResponseContentAsString(httpResponse));
    } else {
      throw new IOException("HttpCode=" + code + " message: " + getResponseContentAsString(httpResponse));
    }
  }

  protected static DefaultHttpClient prepareHttpClient(URI uri, GHCredentials apiCredentials) {
    DefaultHttpClient httpClient = new DefaultHttpClient();
    HttpParams params = httpClient.getParams();
    HttpConnectionParams.setConnectionTimeout(params, 30000);
    HttpConnectionParams.setSoTimeout(params, 30000);
    httpClient.addRequestInterceptor(preemptiveAuth, 0);

    if (apiCredentials != null) {
      httpClient.getCredentialsProvider().setCredentials(new AuthScope(uri.getHost(), uri.getPort(), AuthScope.ANY_SCHEME),
          new UsernamePasswordCredentials(apiCredentials.getUsername(), apiCredentials.getPassword()));
    }
    return httpClient;
  }

  protected static void parseResponseHeaders(Context context, HttpResponse httpResponse, Response<String> ret) {
    Header lm = httpResponse.getLastHeader("Last-Modified");
    Header pi = httpResponse.getLastHeader("X-Poll-Interval");

    Header rll = httpResponse.getLastHeader("X-RateLimit-Limit");
    Header rlr = httpResponse.getLastHeader("X-RateLimit-Remaining");
    Header rlreset = httpResponse.getLastHeader("X-RateLimit-Reset");

    Log.d(TAG, "Response header Last-Modified: " + lm);
    Log.d(TAG, "Response header X-Poll-Interval: " + pi);
    Log.d(TAG, "Response header X-RateLimit-Limit: " + rll);
    Log.d(TAG, "Response header X-RateLimit-Remaining: " + rlr);
    Log.d(TAG, "Response header X-RateLimit-Reset: " + rlreset);

    ret.lastModified = getHeaderValue(lm);
    ret.rateLimit = getHeaderValue(rll);
    ret.rateLimitRemaining = getHeaderValue(rlr);

    String v = getHeaderValue(rlreset);
    if (v != null) {
      try {
        ret.rateLimitReset = Long.parseLong(v) * 1000;
        Log.d(TAG, "Response header X-RateLimit-Reset parsed: " + ret.rateLimitReset);
      } catch (Exception e) {
        Log.w(TAG, "Problem with 'X-RateLimit-Reset' header value '" + v + "' parsing: " + e.getMessage());
      }
    }

    String vpi = getHeaderValue(pi);
    if (vpi != null) {
      try {
        ret.poolInterval = Long.valueOf(vpi);
      } catch (NumberFormatException e) {
        Log.w(TAG, "'X-Poll-Interval' header value is not a number: " + vpi);
      }
    }
  }

  private static void writeReponseInfo(Response<?> response, Context context) {
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putString(PreferencesUtils.INT_SERVERINFO_APILIMIT, response.rateLimit);
    editor.putString(PreferencesUtils.INT_SERVERINFO_APILIMITREMAINING, response.rateLimitRemaining);
    editor.putString(PreferencesUtils.INT_SERVERINFO_APILIMITRESETTIMESTAMP, response.rateLimitReset + "");
    editor.putString(PreferencesUtils.INT_SERVERINFO_LASTREQUESTDURATION, response.requestDuration + "");
    editor.commit();
  }

  private static String getHeaderValue(Header header) {
    if (header != null)
      return Utils.trimToNull(header.getValue());
    return null;
  }

  private static HttpRequestInterceptor preemptiveAuth = new HttpRequestInterceptor() {
    public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
      AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
      CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER);
      HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);

      if (authState.getAuthScheme() == null) {
        AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
        Credentials creds = credsProvider.getCredentials(authScope);
        if (creds != null) {
          authState.setAuthScheme(new BasicScheme());
          authState.setCredentials(creds);
        }
      }
    }
  };

}




Java Source Code List

com.daskiworks.ghwatch.AboutDialogFragment.java
com.daskiworks.ghwatch.ActivityBase.java
com.daskiworks.ghwatch.ActivityTracker.java
com.daskiworks.ghwatch.FullHeightListView.java
com.daskiworks.ghwatch.IabHelper.java
com.daskiworks.ghwatch.LoginDialogFragment.java
com.daskiworks.ghwatch.MainActivity.java
com.daskiworks.ghwatch.MyBackupAgent.java
com.daskiworks.ghwatch.NotificationListAdapter.java
com.daskiworks.ghwatch.NotificationRepositoriesListAdapter.java
com.daskiworks.ghwatch.SettingsActivity.java
com.daskiworks.ghwatch.StartActivity.java
com.daskiworks.ghwatch.SupportAppDevelopmentDialogFragment.java
com.daskiworks.ghwatch.SwipeDismissListViewTouchListener.java
com.daskiworks.ghwatch.UnreadAppWidgetProvider.java
com.daskiworks.ghwatch.Utils.java
com.daskiworks.ghwatch.WatchedRepositoriesActivity.java
com.daskiworks.ghwatch.WatchedRepositoryListAdapter.java
com.daskiworks.ghwatch.alarm.AlarmBroadcastReceiver.java
com.daskiworks.ghwatch.alarm.MarkNotifiationAsReadReceiver.java
com.daskiworks.ghwatch.backend.AuthenticationManager.java
com.daskiworks.ghwatch.backend.GHConstants.java
com.daskiworks.ghwatch.backend.NotificationStreamParser.java
com.daskiworks.ghwatch.backend.OTPAuthenticationException.java
com.daskiworks.ghwatch.backend.PreferencesUtils.java
com.daskiworks.ghwatch.backend.RemoteSystemClient.java
com.daskiworks.ghwatch.backend.UnreadNotificationsService.java
com.daskiworks.ghwatch.backend.ViewDataReloadStrategy.java
com.daskiworks.ghwatch.backend.WatchedRepositoriesParser.java
com.daskiworks.ghwatch.backend.WatchedRepositoriesService.java
com.daskiworks.ghwatch.image.FileCache.java
com.daskiworks.ghwatch.image.ImageLoader.java
com.daskiworks.ghwatch.image.MemoryCache.java
com.daskiworks.ghwatch.model.AccountType.java
com.daskiworks.ghwatch.model.BaseViewData.java
com.daskiworks.ghwatch.model.BooleanViewData.java
com.daskiworks.ghwatch.model.GHCredentials.java
com.daskiworks.ghwatch.model.GHUserInfo.java
com.daskiworks.ghwatch.model.GHUserLoginInfo.java
com.daskiworks.ghwatch.model.LoadingStatus.java
com.daskiworks.ghwatch.model.NotifCount.java
com.daskiworks.ghwatch.model.NotificationStreamViewData.java
com.daskiworks.ghwatch.model.NotificationStream.java
com.daskiworks.ghwatch.model.Notification.java
com.daskiworks.ghwatch.model.Repository.java
com.daskiworks.ghwatch.model.StringViewData.java
com.daskiworks.ghwatch.model.WatchedRepositoriesViewData.java
com.daskiworks.ghwatch.model.WatchedRepositories.java
com.daskiworks.ghwatch.view.preference.ShowTextPreference.java
com.daskiworks.ghwatch.view.preference.ShowTimestampPreference.java