private T doGetTypeRequest(HttpUriRequest request, ActionType actionType)
      throws SocializeException {
    HttpEntity entity = null;

    if (!clientFactory.isDestroyed()) {

      try {

        HttpClient client = clientFactory.getClient();

        HttpResponse response = executeRequest(client, request);

        entity = response.getEntity();

        if (httpUtils.isHttpError(response)) {

          if (sessionPersister != null && httpUtils.isAuthError(response)) {
            sessionPersister.delete(context);
          }

          String msg = ioUtils.readSafe(entity.getContent());
          throw new SocializeApiError(httpUtils, response.getStatusLine().getStatusCode(), msg);
        } else {
          JSONObject json = jsonParser.parseObject(entity.getContent());

          return fromJSON(json, actionType);
        }
      } catch (Exception e) {
        throw SocializeException.wrap(e);
      } finally {
        closeEntity(entity);
      }
    } else {
      if (logger != null) {
        logger.warn("Attempt to access HttpClientFactory that was already destroyed");
      }

      return null;
    }
  }
  @Override
  public void delete(SocializeSession session, String endpoint, String id)
      throws SocializeException {
    HttpEntity entity = null;

    if (!clientFactory.isDestroyed()) {
      try {
        endpoint = prepareEndpoint(session, endpoint);

        HttpClient client = clientFactory.getClient();

        HttpUriRequest del = requestFactory.getDeleteRequest(session, endpoint, id);

        HttpResponse response = client.execute(del);

        entity = response.getEntity();

        if (httpUtils.isHttpError(response)) {

          if (sessionPersister != null && httpUtils.isAuthError(response)) {
            sessionPersister.delete(context);
          }

          String msg = ioUtils.readSafe(entity.getContent());
          throw new SocializeApiError(httpUtils, response.getStatusLine().getStatusCode(), msg);
        }
      } catch (Exception e) {
        throw SocializeException.wrap(e);
      } finally {
        closeEntity(entity);
      }
    } else {
      if (logger != null) {
        logger.warn("Attempt to access HttpClientFactory that was already destroyed");
      }
    }
  }
  private ListResult<T> doListTypeRequest(
      HttpUriRequest request, ActionType type, boolean isJSONResponse) throws SocializeException {
    List<T> results = null;
    List<ActionError> errors = null;
    HttpEntity entity = null;

    ListResult<T> result = null;

    if (!clientFactory.isDestroyed()) {

      try {
        HttpClient client = clientFactory.getClient();

        if (logger != null && logger.isDebugEnabled()) {
          logger.debug("Request: " + request.getMethod() + " " + request.getRequestLine().getUri());
        }

        HttpResponse response = executeRequest(client, request);

        if (logger != null && logger.isDebugEnabled()) {
          logger.debug("Response: " + response.getStatusLine().getStatusCode());
        }

        entity = response.getEntity();

        if (httpUtils.isHttpError(response)) {

          if (sessionPersister != null && httpUtils.isAuthError(response)) {
            sessionPersister.delete(context);
          }

          String msg = ioUtils.readSafe(entity.getContent());
          throw new SocializeApiError(httpUtils, response.getStatusLine().getStatusCode(), msg);
        } else {

          result = new ListResult<T>();

          if (isJSONResponse) {
            // Read the json just for logging
            String json = ioUtils.readSafe(entity.getContent());

            if (logger != null && logger.isDebugEnabled()) {
              logger.debug("JSON Response: " + json);
            }

            if (!StringUtils.isEmpty(json)) {
              JSONObject object = jsonParser.parseObject(json);

              if (object.has(JSON_ATTR_ERRORS) && !object.isNull(JSON_ATTR_ERRORS)) {

                JSONArray errorList = object.getJSONArray(JSON_ATTR_ERRORS);

                int length = errorList.length();

                errors = new ArrayList<ActionError>(length);

                for (int i = 0; i < length; i++) {
                  JSONObject jsonObject = errorList.getJSONObject(i);
                  ActionError error = errorFactory.fromJSON(jsonObject);
                  errors.add(error);
                }

                result.setErrors(errors);
              }

              if (object.has(JSON_ATTR_ITEMS) && !object.isNull(JSON_ATTR_ITEMS)) {
                JSONArray list = object.getJSONArray(JSON_ATTR_ITEMS);

                int length = list.length();

                results = new ArrayList<T>(length);

                for (int i = 0; i < length; i++) {
                  results.add(fromJSON(list.getJSONObject(i), type));
                }

                result.setItems(results);
              }

              if (object.has(JSON_ATTR_COUNT) && !object.isNull(JSON_ATTR_COUNT)) {
                result.setTotalCount(object.getInt(JSON_ATTR_COUNT));
              }
            }
          }
        }
      } catch (Throwable e) {
        throw SocializeException.wrap(e);
      } finally {
        closeEntity(entity);
      }

      return result;
    } else {
      if (logger != null) {
        logger.warn("Attempt to access HttpClientFactory that was already destroyed");
      }

      return null;
    }
  }
  @Override
  public SocializeSession authenticate(
      String endpoint, String key, String secret, AuthProviderData data, String uuid)
      throws SocializeException {
    try {
      SessionLock.lock();

      WritableSession session = loadSession(endpoint, key, secret);

      if (session != null) {

        if (validateSession(session, data)) {
          return session;
        } else {
          session = setProviderCredentialsForUser(data, session);
        }
      }

      if (session == null) {
        session = sessionFactory.create(key, secret, data);
      }

      endpoint = prepareEndpoint(session, endpoint, true);

      if (!clientFactory.isDestroyed()) {

        HttpClient client = clientFactory.getClient();

        HttpEntity entity = null;

        try {
          HttpUriRequest request = requestFactory.getAuthRequest(session, endpoint, uuid, data);

          if (logger != null && logger.isDebugEnabled()) {
            logger.debug("Calling authenticate endpoint for device [" + uuid + "]");
          }

          HttpResponse response = executeRequest(client, request);

          entity = response.getEntity();

          if (httpUtils.isHttpError(response)) {

            if (sessionPersister != null && httpUtils.isAuthError(response)) {
              sessionPersister.delete(context);
            }

            String msg = ioUtils.readSafe(entity.getContent());

            throw new SocializeApiError(httpUtils, response.getStatusLine().getStatusCode(), msg);
          } else {

            JSONObject json = jsonParser.parseObject(entity.getContent());

            User user = userFactory.fromJSON(json.getJSONObject("user"));

            String oauth_token = json.getString("oauth_token");
            String oauth_token_secret = json.getString("oauth_token_secret");

            if (StringUtils.isEmpty(oauth_token)) {
              throw new SocializeException("oauth_token was empty in response from server");
            }

            if (StringUtils.isEmpty(oauth_token_secret)) {
              throw new SocializeException("oauth_token_secret was empty in response from server");
            }

            session.setConsumerToken(oauth_token);
            session.setConsumerTokenSecret(oauth_token_secret);
            session.setUser(user);

            setProviderCredentialsForUser(data, session);

            // Ensure the user credentials match the user auth data returned from the server
            verifyProviderCredentialsForUser(session, user);

            saveSession(session);
          }
        } catch (Exception e) {
          throw SocializeException.wrap(e);
        } finally {
          closeEntity(entity);
        }
      } else {
        if (logger != null) {
          logger.warn("Attempt to access HttpClientFactory that was already destroyed");
        }
      }

      return session;
    } finally {
      SessionLock.unlock();
    }
  }