/** 连接网络读取数据 */
  @Override
  protected <T> void connectWithRetries(AbstractRequest<T> request, InternalResponse response)
      throws HttpClientException, HttpNetException, HttpServerException {

    // if(true) {
    //    throw new HttpNetException(NetException.NetworkDisabled);
    // }

    // 1. create apache request
    final HttpUriRequest apacheRequest = createApacheRequest(request);

    // 2. update http header
    if (request.getHeaders() != null) {
      Set<Entry<String, String>> set = request.getHeaders().entrySet();
      for (Entry<String, String> en : set) {
        apacheRequest.setHeader(new BasicHeader(en.getKey(), en.getValue()));
      }
    }

    // 3. try to connect
    HttpListener<T> listener = request.getHttpListener();
    StatisticsListener statistic = response.getStatistics();
    int times = 0,
        maxRetryTimes = request.getMaxRetryTimes(),
        maxRedirectTimes = request.getMaxRedirectTimes();
    boolean retry = true;
    IOException cause = null;
    while (retry) {
      try {
        cause = null;
        retry = false;
        if (request.isCancelledOrInterrupted()) {
          return;
        }
        if (statistic != null) {
          statistic.onPreConnect(request);
        }
        HttpResponse ares = mHttpClient.execute(apacheRequest);
        if (statistic != null) {
          statistic.onAfterConnect(request);
        }
        // status
        StatusLine status = ares.getStatusLine();
        HttpStatus httpStatus = new HttpStatus(status.getStatusCode(), status.getReasonPhrase());
        response.setHttpStatus(httpStatus);
        // header
        Header[] headers = ares.getAllHeaders();
        if (headers != null) {
          com.litesuits.http.data.NameValuePair hs[] =
              new com.litesuits.http.data.NameValuePair[headers.length];
          for (int i = 0; i < headers.length; i++) {
            String name = headers[i].getName();
            String value = headers[i].getValue();
            if ("Content-Length".equalsIgnoreCase(name)) {
              response.setContentLength(Long.parseLong(value));
            }
            hs[i] = new com.litesuits.http.data.NameValuePair(name, value);
          }
          response.setHeaders(hs);
        }

        // data body
        if (status.getStatusCode() <= 299 || status.getStatusCode() == 600) {
          // 成功
          HttpEntity entity = ares.getEntity();
          if (entity != null) {
            // charset
            String charSet = getCharsetFromEntity(entity, request.getCharSet());
            response.setCharSet(charSet);
            // is cancelled ?
            if (request.isCancelledOrInterrupted()) {
              return;
            }
            // length
            long len = response.getContentLength();
            DataParser<T> parser = request.getDataParser();
            if (statistic != null) {
              statistic.onPreRead(request);
            }
            parser.readFromNetStream(entity.getContent(), len, charSet);
            if (statistic != null) {
              statistic.onAfterRead(request);
            }
            response.setReadedLength(parser.getReadedLength());
            endEntityViaReflection(entity);
          }
          return;
        } else if (status.getStatusCode() <= 399) {
          // redirect
          if (response.getRedirectTimes() < maxRedirectTimes) {
            // get the location header to find out where to redirect to
            Header locationHeader = ares.getFirstHeader(Consts.REDIRECT_LOCATION);
            if (locationHeader != null) {
              String location = locationHeader.getValue();
              if (location != null && location.length() > 0) {
                if (!location.toLowerCase().startsWith("http")) {
                  URI uri = new URI(request.getFullUri());
                  URI redirect = new URI(uri.getScheme(), uri.getHost(), location, null);
                  location = redirect.toString();
                }
                response.setRedirectTimes(response.getRedirectTimes() + 1);
                request.setUri(location);
                if (HttpLog.isPrint) {
                  HttpLog.i(TAG, "Redirect to : " + location);
                }
                if (listener != null) {
                  listener.notifyCallRedirect(
                      request, maxRedirectTimes, response.getRedirectTimes());
                }
                connectWithRetries(request, response);
                return;
              }
            }
            throw new HttpServerException(httpStatus);
          } else {
            throw new HttpServerException(ServerException.RedirectTooMuch);
          }
        } else if (status.getStatusCode() <= 499) {
          // 客户端被拒
          throw new HttpServerException(httpStatus);
        } else if (status.getStatusCode() < 599) {
          // 服务器有误
          throw new HttpServerException(httpStatus);
        }
      } catch (IOException e) {
        cause = e;
      } catch (NullPointerException e) {
        // bug in HttpClient 4.0.x, see http://code.google.com/p/android/issues/detail?id=5255
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
          cause = new IOException(e.getMessage());
        } else {
          cause = new IOException(e);
        }
      } catch (URISyntaxException e) {
        throw new HttpClientException(e);
      } catch (IllegalStateException e) {
        // for apache http client. if url is illegal, it usually raises an exception as
        // "IllegalStateException:
        // Scheme 'xxx' not registered."
        throw new HttpClientException(e);
      } catch (SecurityException e) {
        throw new HttpClientException(e, ClientException.PermissionDenied);
      } catch (RuntimeException e) {
        throw new HttpClientException(e);
      }
      if (cause != null) {
        try {
          if (request.isCancelledOrInterrupted()) {
            return;
          }
          times++;
          retry =
              retryHandler.retryRequest(
                  cause, times, maxRetryTimes, mHttpContext, config.getContext());
        } catch (InterruptedException e) {
          e.printStackTrace();
          return;
        }
        if (retry) {
          response.setRetryTimes(times);
          if (HttpLog.isPrint) {
            HttpLog.i(TAG, "LiteHttp retry request: " + request.getUri());
          }
          if (listener != null) {
            listener.notifyCallRetry(request, maxRetryTimes, times);
          }
        }
      }
    }
    if (cause != null) {
      throw new HttpNetException(cause);
    }
  }
Esempio n. 2
0
  @Override
  @SuppressWarnings("unchecked")
  protected ResultType doBackground() throws Throwable {

    if (this.isCancelled()) {
      throw new Callback.CancelledException("cancelled before request");
    }

    // 初始化请求参数
    ResultType result = null;
    boolean retry = true;
    int retryCount = 0;
    Throwable exception = null;
    HttpRetryHandler retryHandler = new HttpRetryHandler(this.params.getMaxRetryCount());
    request = initRequest();

    if (this.isCancelled()) {
      throw new Callback.CancelledException("cancelled before request");
    }

    // 检查缓存
    Object cacheResult = null;
    if (cacheCallback != null && HttpMethod.permitsCache(params.getMethod())) {
      // 尝试从缓存获取结果, 并为请求头加入缓存控制参数.
      while (retry) {
        try {
          clearRawResult();
          rawResult = this.request.loadResultFromCache();
          break;
        } catch (Throwable ex) {
          LogUtil.w("load disk cache error", ex);
          exception = ex;
          retry = retryHandler.retryRequest(ex, ++retryCount, this.request);
        }
      }

      if (this.isCancelled()) {
        clearRawResult();
        throw new Callback.CancelledException("cancelled before request");
      }

      if (rawResult != null) {
        if (prepareCallback != null) {
          try {
            cacheResult = prepareCallback.prepare(rawResult);
          } catch (Throwable ex) {
            cacheResult = null;
            LogUtil.w("prepare disk cache error", ex);
          } finally {
            clearRawResult();
          }
        } else {
          cacheResult = rawResult;
        }

        if (this.isCancelled()) {
          throw new Callback.CancelledException("cancelled before request");
        }

        if (cacheResult != null) {
          // 同步等待是否信任缓存
          this.update(FLAG_CACHE, cacheResult);
          while (trustCache == null) {
            synchronized (cacheLock) {
              try {
                cacheLock.wait();
              } catch (Throwable ignored) {
              }
            }
          }

          // 处理完成
          if (trustCache) {
            return null;
          }
        }
      }
    }

    if (trustCache == null) {
      trustCache = false;
    }

    if (cacheResult == null) {
      this.request.clearCacheHeader();
    }

    // 发起请求
    retry = true;
    while (retry) {

      try {
        if (this.isCancelled()) {
          throw new Callback.CancelledException("cancelled before request");
        }

        // 由loader发起请求, 拿到结果.
        this.request.close(); // retry 前关闭上次请求

        try {
          clearRawResult();
          requestWorker = new RequestWorker(this.request, this.loadType);
          if (params.isCancelFast()) {
            requestWorker.start();
            requestWorker.join();
          } else {
            requestWorker.run();
          }
          if (requestWorker.ex != null) {
            throw requestWorker.ex;
          }
          rawResult = requestWorker.result;
        } catch (Throwable ex) {
          clearRawResult();
          if (this.isCancelled()) {
            throw new Callback.CancelledException("cancelled during request");
          } else {
            throw ex;
          }
        }

        if (prepareCallback != null) {
          try {
            result = (ResultType) prepareCallback.prepare(rawResult);
          } finally {
            clearRawResult();
          }
        } else {
          result = (ResultType) rawResult;
        }

        // 保存缓存
        if (cacheCallback != null && HttpMethod.permitsCache(params.getMethod())) {
          this.request.save2Cache();
        }

        retry = false;

        if (this.isCancelled()) {
          throw new Callback.CancelledException("cancelled after request");
        }
      } catch (Throwable ex) {
        if (this.request.getResponseCode() == 304) { // disk cache is valid.
          return null;
        } else {
          exception = ex;
          retry = retryHandler.retryRequest(ex, ++retryCount, this.request);
        }
      }
    }

    if (exception != null && result == null && !trustCache) {
      throw exception;
    }

    return result;
  }