Esempio n. 1
0
  /**
   * Creates a new fetcher for fetching HTTP objects. Not really suitable for production use. Use of
   * an HTTP proxy for security is also necessary for production deployment.
   *
   * @param maxObjSize Maximum size, in bytes, of the object we will fetch, 0 if no limit..
   * @param connectionTimeoutMs timeout, in milliseconds, for connecting to hosts.
   * @param readTimeoutMs timeout, in millseconds, for unresponsive connections
   * @param basicHttpFetcherProxy The http proxy to use.
   */
  public BasicHttpFetcher(
      int maxObjSize, int connectionTimeoutMs, int readTimeoutMs, String basicHttpFetcherProxy) {
    // Create and initialize HTTP parameters
    setMaxObjectSizeBytes(maxObjSize);
    setSlowResponseWarning(DEFAULT_SLOW_RESPONSE_WARNING);

    HttpParams params = new BasicHttpParams();

    ConnManagerParams.setTimeout(params, connectionTimeoutMs);

    // These are probably overkill for most sites.
    ConnManagerParams.setMaxTotalConnections(params, 1152);
    ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(256));

    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    HttpProtocolParams.setUserAgent(params, "Apache Shindig");
    HttpProtocolParams.setContentCharset(params, "UTF-8");

    HttpConnectionParams.setConnectionTimeout(params, connectionTimeoutMs);
    HttpConnectionParams.setSoTimeout(params, readTimeoutMs);
    HttpConnectionParams.setStaleCheckingEnabled(params, true);

    HttpClientParams.setRedirecting(params, true);
    HttpClientParams.setAuthenticating(params, false);

    // Create and initialize scheme registry
    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    // UCSF. Change to allow self signed registered certs
    /**
     * try { SSLContext sslContext = SSLContext.getInstance("SSL"); // set up a TrustManager that
     * trusts everything sslContext.init(null, new TrustManager[] { new X509TrustManager() { public
     * X509Certificate[] getAcceptedIssuers() { System.out.println("getAcceptedIssuers
     * ============="); return null; }
     *
     * <p>public void checkClientTrusted(X509Certificate[] certs, String authType) {
     * System.out.println("checkClientTrusted ============="); }
     *
     * <p>public void checkServerTrusted(X509Certificate[] certs, String authType) {
     * System.out.println("checkServerTrusted ============="); } } }, new SecureRandom());
     * SSLSocketFactory sf = new SSLSocketFactory(sslContext);
     * sf.setHostnameVerifier((X509HostnameVerifier)org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
     * schemeRegistry.register(new Scheme("https", sf, 443)); } catch (Exception e) { throw new
     * RuntimeException(e); }
     */
    schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
    // end UCSF

    ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
    DefaultHttpClient client = new DefaultHttpClient(cm, params);

    // Set proxy if set via guice.
    if (!StringUtils.isEmpty(basicHttpFetcherProxy)) {
      String[] splits = basicHttpFetcherProxy.split(":");
      ConnRouteParams.setDefaultProxy(
          client.getParams(), new HttpHost(splits[0], Integer.parseInt(splits[1]), "http"));
    }

    // try resending the request once
    client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(1, true));

    // Add hooks for gzip/deflate
    client.addRequestInterceptor(
        new HttpRequestInterceptor() {
          public void process(final org.apache.http.HttpRequest request, final HttpContext context)
              throws HttpException, IOException {
            if (!request.containsHeader("Accept-Encoding")) {
              request.addHeader("Accept-Encoding", "gzip, deflate");
            }
          }
        });
    client.addResponseInterceptor(
        new HttpResponseInterceptor() {
          public void process(
              final org.apache.http.HttpResponse response, final HttpContext context)
              throws HttpException, IOException {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
              Header ceheader = entity.getContentEncoding();
              if (ceheader != null) {
                for (HeaderElement codec : ceheader.getElements()) {
                  String codecname = codec.getName();
                  if ("gzip".equalsIgnoreCase(codecname)) {
                    response.setEntity(new GzipDecompressingEntity(response.getEntity()));
                    return;
                  } else if ("deflate".equals(codecname)) {
                    response.setEntity(new DeflateDecompressingEntity(response.getEntity()));
                    return;
                  }
                }
              }
            }
          }
        });
    client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler());

    // Disable automatic storage and sending of cookies (see SHINDIG-1382)
    client.removeRequestInterceptorByClass(RequestAddCookies.class);
    client.removeResponseInterceptorByClass(ResponseProcessCookies.class);

    // Use Java's built-in proxy logic in case no proxy set via guice.
    if (StringUtils.isEmpty(basicHttpFetcherProxy)) {
      ProxySelectorRoutePlanner routePlanner =
          new ProxySelectorRoutePlanner(
              client.getConnectionManager().getSchemeRegistry(), ProxySelector.getDefault());
      client.setRoutePlanner(routePlanner);
    }

    FETCHER = client;
  }
  /**
   * A helper method to send or retrieve data through HTTP protocol.
   *
   * @param token The token to identify the sending progress.
   * @param url The URL used in a GET request. Null when the method is HTTP_POST_METHOD.
   * @param pdu The data to be POST. Null when the method is HTTP_GET_METHOD.
   * @param method HTTP_POST_METHOD or HTTP_GET_METHOD.
   * @return A byte array which contains the response data. If an HTTP error code is returned, an
   *     IOException will be thrown.
   * @throws IOException if any error occurred on network interface or an HTTP error code(&gt;=400)
   *     returned from the server.
   */
  protected static byte[] httpConnection(
      Context context,
      long token,
      String url,
      byte[] pdu,
      int method,
      boolean isProxySet,
      String proxyHost,
      int proxyPort)
      throws IOException {
    if (url == null) {
      throw new IllegalArgumentException("URL must not be null.");
    }

    if (LOCAL_LOGV) {
      Log.v(TAG, "httpConnection: params list");
      Log.v(TAG, "\ttoken\t\t= " + token);
      Log.v(TAG, "\turl\t\t= " + url);
      Log.v(TAG, "\tUser-Agent\t\t=" + mUserAgent);
      Log.v(
          TAG,
          "\tmethod\t\t= "
              + ((method == HTTP_POST_METHOD)
                  ? "POST"
                  : ((method == HTTP_GET_METHOD) ? "GET" : "UNKNOWN")));
      Log.v(TAG, "\tisProxySet\t= " + isProxySet);
      Log.v(TAG, "\tproxyHost\t= " + proxyHost);
      Log.v(TAG, "\tproxyPort\t= " + proxyPort);
      // TODO Print out binary data more readable.
      // Log.v(TAG, "\tpdu\t\t= " + Arrays.toString(pdu));
    }

    AndroidHttpClient client = null;

    try {
      // Make sure to use a proxy which supports CONNECT.
      URI hostUrl = new URI(url);
      HttpHost target =
          new HttpHost(hostUrl.getHost(), hostUrl.getPort(), HttpHost.DEFAULT_SCHEME_NAME);

      client = createHttpClient(context);
      HttpRequest req = null;
      switch (method) {
        case HTTP_POST_METHOD:
          ProgressCallbackEntity entity = new ProgressCallbackEntity(context, token, pdu);
          // Set request content type.
          entity.setContentType("application/vnd.wap.mms-message");

          HttpPost post = new HttpPost(url);
          post.setEntity(entity);
          req = post;
          break;
        case HTTP_GET_METHOD:
          req = new HttpGet(url);
          break;
        default:
          Log.e(
              TAG,
              "Unknown HTTP method: "
                  + method
                  + ". Must be one of POST["
                  + HTTP_POST_METHOD
                  + "] or GET["
                  + HTTP_GET_METHOD
                  + "].");
          return null;
      }

      // Set route parameters for the request.
      HttpParams params = client.getParams();
      if (isProxySet) {
        ConnRouteParams.setDefaultProxy(params, new HttpHost(proxyHost, proxyPort));
      }
      req.setParams(params);

      // Set necessary HTTP headers for MMS transmission.
      req.addHeader(HDR_KEY_ACCEPT, HDR_VALUE_ACCEPT);
      {
        String xWapProfileTagName = MmsConfig.getUaProfTagName();
        String xWapProfileUrl = MmsConfig.getUaProfUrl();

        if (xWapProfileUrl != null) {
          if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
            Log.d(LogTag.TRANSACTION, "[HttpUtils] httpConn: xWapProfUrl=" + xWapProfileUrl);
          }
          req.addHeader(xWapProfileTagName, xWapProfileUrl);
        }
      }

      // Extra http parameters. Split by '|' to get a list of value pairs.
      // Separate each pair by the first occurrence of ':' to obtain a name and
      // value. Replace the occurrence of the string returned by
      // MmsConfig.getHttpParamsLine1Key() with the users telephone number inside
      // the value.
      String extraHttpParams = MmsConfig.getHttpParams();

      if (extraHttpParams != null) {
        String line1Number =
            ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
                .getLine1Number();
        String line1Key = MmsConfig.getHttpParamsLine1Key();
        String paramList[] = extraHttpParams.split("\\|");

        for (String paramPair : paramList) {
          String splitPair[] = paramPair.split(":", 2);

          if (splitPair.length == 2) {
            String name = splitPair[0].trim();
            String value = splitPair[1].trim();

            if (line1Key != null) {
              value = value.replace(line1Key, line1Number);
            }
            if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(value)) {
              req.addHeader(name, value);
            }
          }
        }
      }
      req.addHeader(HDR_KEY_ACCEPT_LANGUAGE, HDR_VALUE_ACCEPT_LANGUAGE);

      HttpResponse response = client.execute(target, req);
      StatusLine status = response.getStatusLine();
      if (status.getStatusCode() != 200) { // HTTP 200 is success.
        throw new IOException("HTTP error: " + status.getReasonPhrase());
      }

      HttpEntity entity = response.getEntity();
      byte[] body = null;
      if (entity != null) {
        try {
          if (entity.getContentLength() > 0) {
            body = new byte[(int) entity.getContentLength()];
            DataInputStream dis = new DataInputStream(entity.getContent());
            try {
              dis.readFully(body);
            } finally {
              try {
                dis.close();
              } catch (IOException e) {
                Log.e(TAG, "Error closing input stream: " + e.getMessage());
              }
            }
          }
        } finally {
          if (entity != null) {
            entity.consumeContent();
          }
        }
      }
      return body;
    } catch (URISyntaxException e) {
      handleHttpConnectionException(e, url);
    } catch (IllegalStateException e) {
      handleHttpConnectionException(e, url);
    } catch (IllegalArgumentException e) {
      handleHttpConnectionException(e, url);
    } catch (SocketException e) {
      handleHttpConnectionException(e, url);
    } catch (Exception e) {
      handleHttpConnectionException(e, url);
    } finally {
      if (client != null) {
        client.close();
      }
    }
    return null;
  }