@Test
  public void testFullFileDecryption() throws IOException, URISyntaxException {
    final URL testResourceUrl = new URL(VAULT_BASE_URI.toURL(), "fullFileDecryptionTestFile.txt");
    final HttpClient client = new HttpClient();

    // prepare 64MiB test data:
    final byte[] plaintextData = new byte[16777216 * Integer.BYTES];
    final ByteBuffer bbIn = ByteBuffer.wrap(plaintextData);
    for (int i = 0; i < 16777216; i++) {
      bbIn.putInt(i);
    }
    final InputStream plaintextDataInputStream = new ByteArrayInputStream(plaintextData);

    // put request:
    final EntityEnclosingMethod putMethod = new PutMethod(testResourceUrl.toString());
    putMethod.setRequestEntity(new ByteArrayRequestEntity(plaintextData));
    final int putResponse = client.executeMethod(putMethod);
    putMethod.releaseConnection();
    Assert.assertEquals(201, putResponse);

    // get request:
    final HttpMethod getMethod = new GetMethod(testResourceUrl.toString());
    final int statusCode = client.executeMethod(getMethod);
    Assert.assertEquals(200, statusCode);
    // final byte[] received = new byte[plaintextData.length];
    // IOUtils.read(getMethod.getResponseBodyAsStream(), received);
    // Assert.assertArrayEquals(plaintextData, received);
    Assert.assertTrue(
        IOUtils.contentEquals(plaintextDataInputStream, getMethod.getResponseBodyAsStream()));
    getMethod.releaseConnection();
  }
  @Test
  public void testUnsatisfiableRangeRequest() throws IOException, URISyntaxException {
    final URL testResourceUrl =
        new URL(VAULT_BASE_URI.toURL(), "unsatisfiableRangeRequestTestFile.txt");
    final HttpClient client = new HttpClient();

    // prepare file content:
    final byte[] fileContent = "This is some test file content.".getBytes();

    // put request:
    final EntityEnclosingMethod putMethod = new PutMethod(testResourceUrl.toString());
    putMethod.setRequestEntity(new ByteArrayRequestEntity(fileContent));
    final int putResponse = client.executeMethod(putMethod);
    putMethod.releaseConnection();
    Assert.assertEquals(201, putResponse);

    // get request:
    final HttpMethod getMethod = new GetMethod(testResourceUrl.toString());
    getMethod.addRequestHeader("Range", "chunks=1-2");
    final int getResponse = client.executeMethod(getMethod);
    final byte[] response = new byte[fileContent.length];
    IOUtils.read(getMethod.getResponseBodyAsStream(), response);
    getMethod.releaseConnection();
    Assert.assertEquals(416, getResponse);
    Assert.assertArrayEquals(fileContent, response);
  }
示例#3
0
  public String postApp(String url, String xml) {
    EntityEnclosingMethod httpMethod = new PostMethod(url);
    try {
      RequestEntity entity = new StringRequestEntity(xml, APP_XML, UTF_8);
      httpMethod.setRequestEntity(entity);
    } catch (UnsupportedEncodingException e) {
    }

    return sendApp(httpMethod);
  }
示例#4
0
  /**
   * 发送http请求,并返回响应的xml报文 <功能详细描述>
   *
   * @param url http请求url
   * @param xml 请求xml报文
   * @return
   */
  public String post(String url, String xml) {
    EntityEnclosingMethod httpMethod = new PostMethod(url);

    // 发送含xml消息体的对象
    try {
      RequestEntity entity = new StringRequestEntity(xml, TEXT_XML, UTF_8);
      httpMethod.setRequestEntity(entity);
    } catch (UnsupportedEncodingException e) {
      LogUtil.error(e.getMessage(), e);
    }

    return send(httpMethod);
  }
示例#5
0
  /**
   * Update entry by posting new representation of entry to server. Note that you should not attempt
   * to update entries that you get from iterating over a collection they may be "partial" entries.
   * If you want to update an entry, you must get it via one of the <code>getEntry()</code> methods
   * in {@link com.sun.syndication.propono.atom.common.Collection} or {@link
   * com.sun.syndication.propono.atom.common.AtomService}.
   *
   * @throws ProponoException If entry is a "partial" entry.
   */
  public void update() throws ProponoException {
    if (partial) throw new ProponoException("ERROR: attempt to update partial entry");
    EntityEnclosingMethod method = new PutMethod(getEditURI());
    addAuthentication(method);
    StringWriter sw = new StringWriter();
    int code = -1;
    try {
      Atom10Generator.serializeEntry(this, sw);
      method.setRequestEntity(new StringRequestEntity(sw.toString()));
      method.setRequestHeader("Content-type", "application/atom+xml; charset=utf-8");
      getHttpClient().executeMethod(method);
      InputStream is = method.getResponseBodyAsStream();
      if (method.getStatusCode() != 200 && method.getStatusCode() != 201) {
        throw new ProponoException(
            "ERROR HTTP status=" + method.getStatusCode() + " : " + Utilities.streamToString(is));
      }

    } catch (Exception e) {
      String msg = "ERROR: updating entry, HTTP code: " + code;
      logger.debug(msg, e);
      throw new ProponoException(msg, e);
    } finally {
      method.releaseConnection();
    }
  }
 /**
  * Adds the JSON as request-body the the method and sets the correct content-type.
  *
  * @param method
  * @param object
  */
 public static void populateRequestBody(EntityEnclosingMethod method, JSONObject object) {
   try {
     method.setRequestEntity(
         new StringRequestEntity(object.toJSONString(), MIME_TYPE_JSON, "UTF-8"));
   } catch (UnsupportedEncodingException error) {
     // This will never happen!
     throw new RuntimeException("All hell broke loose, a JVM that doesn't have UTF-8 encoding...");
   }
 }
  @Override
  protected void proxy(
      String targetUrl, final HttpServletRequest request, final HttpServletResponse response)
      throws IOException {

    final HttpMethod proxyRequest = createProxyRequest(targetUrl, request);

    if (proxyRequest instanceof EntityEnclosingMethod) {
      EntityEnclosingMethod entityEnclosingMethod = (EntityEnclosingMethod) proxyRequest;
      RequestEntity requestEntity =
          new InputStreamRequestEntity(
              request.getInputStream(), request.getContentLength(), request.getContentType());
      entityEnclosingMethod.setRequestEntity(requestEntity);
    }
    int code = httpClient.executeMethod(proxyRequest);
    response.setStatus(code);
    copyProxyReponse(proxyRequest, response);
  }
示例#8
0
  /**
   * Creates the HttpMethod to use to call the remote server, either its GET or POST.
   *
   * @param exchange the exchange
   * @return the created method as either GET or POST
   * @throws CamelExchangeException is thrown if error creating RequestEntity
   */
  @SuppressWarnings("deprecation")
  protected HttpMethod createMethod(Exchange exchange) throws Exception {
    // creating the url to use takes 2-steps
    String url = HttpHelper.createURL(exchange, getEndpoint());
    URI uri = HttpHelper.createURI(exchange, url, getEndpoint());
    // get the url and query string from the uri
    url = uri.toASCIIString();
    String queryString = uri.getRawQuery();

    // execute any custom url rewrite
    String rewriteUrl = HttpHelper.urlRewrite(exchange, url, getEndpoint(), this);
    if (rewriteUrl != null) {
      // update url and query string from the rewritten url
      url = rewriteUrl;
      uri = new URI(url);
      // use raw query to have uri decimal encoded which http client requires
      queryString = uri.getRawQuery();
    }

    // remove query string as http client does not accept that
    if (url.indexOf('?') != -1) {
      url = url.substring(0, url.indexOf('?'));
    }

    // create http holder objects for the request
    RequestEntity requestEntity = createRequestEntity(exchange);
    HttpMethods methodToUse =
        HttpHelper.createMethod(exchange, getEndpoint(), requestEntity != null);
    HttpMethod method = methodToUse.createMethod(url);
    if (queryString != null) {
      // need to encode query string
      queryString = UnsafeUriCharactersEncoder.encode(queryString);
      method.setQueryString(queryString);
    }

    LOG.trace("Using URL: {} with method: {}", url, method);

    if (methodToUse.isEntityEnclosing()) {
      ((EntityEnclosingMethod) method).setRequestEntity(requestEntity);
      if (requestEntity != null && requestEntity.getContentType() == null) {
        LOG.debug("No Content-Type provided for URL: {} with exchange: {}", url, exchange);
      }
    }

    // there must be a host on the method
    if (method.getHostConfiguration().getHost() == null) {
      throw new IllegalArgumentException(
          "Invalid uri: "
              + url
              + ". If you are forwarding/bridging http endpoints, then enable the bridgeEndpoint option on the endpoint: "
              + getEndpoint());
    }

    return method;
  }
示例#9
0
  void addToCollection(ClientCollection col) throws ProponoException {
    setCollection(col);
    EntityEnclosingMethod method = new PostMethod(getCollection().getHrefResolved());
    addAuthentication(method);
    StringWriter sw = new StringWriter();
    int code = -1;
    try {
      Atom10Generator.serializeEntry(this, sw);
      method.setRequestEntity(new StringRequestEntity(sw.toString()));
      method.setRequestHeader("Content-type", "application/atom+xml; charset=utf-8");
      getHttpClient().executeMethod(method);
      InputStream is = method.getResponseBodyAsStream();
      code = method.getStatusCode();
      if (code != 200 && code != 201) {
        throw new ProponoException(
            "ERROR HTTP status=" + code + " : " + Utilities.streamToString(is));
      }
      Entry romeEntry =
          Atom10Parser.parseEntry(new InputStreamReader(is), getCollection().getHrefResolved());
      BeanUtils.copyProperties(this, romeEntry);

    } catch (Exception e) {
      String msg = "ERROR: saving entry, HTTP code: " + code;
      logger.debug(msg, e);
      throw new ProponoException(msg, e);
    } finally {
      method.releaseConnection();
    }
    Header locationHeader = method.getResponseHeader("Location");
    if (locationHeader == null) {
      logger.warn("WARNING added entry, but no location header returned");
    } else if (getEditURI() == null) {
      List links = getOtherLinks();
      Link link = new Link();
      link.setHref(locationHeader.getValue());
      link.setRel("edit");
      links.add(link);
      setOtherLinks(links);
    }
  }
示例#10
0
  /**
   * Sends the request to the client. Commits the request line, headers and optional entity and send
   * them over the network.
   *
   * @param request The high-level request.
   * @return The result status.
   */
  @Override
  public Status sendRequest(Request request) {
    Status result = null;

    try {
      final Representation entity = request.getEntity();

      // Set the request headers
      for (final Parameter header : getRequestHeaders()) {
        getHttpMethod().addRequestHeader(header.getName(), header.getValue());
      }

      // For those method that accept enclosing entites, provide it
      if ((entity != null) && (getHttpMethod() instanceof EntityEnclosingMethod)) {
        final EntityEnclosingMethod eem = (EntityEnclosingMethod) getHttpMethod();
        eem.setRequestEntity(
            new RequestEntity() {
              public long getContentLength() {
                return entity.getSize();
              }

              public String getContentType() {
                return (entity.getMediaType() != null) ? entity.getMediaType().toString() : null;
              }

              public boolean isRepeatable() {
                return !entity.isTransient();
              }

              public void writeRequest(OutputStream os) throws IOException {
                entity.write(os);
              }
            });
      }

      // Ensure that the connection is active
      this.clientHelper.getHttpClient().executeMethod(getHttpMethod());

      // Now we can access the status code, this MUST happen after closing
      // any open request stream.
      result = new Status(getStatusCode(), null, getReasonPhrase(), null);

      // If there is no response body, immediately release the connection
      if (getHttpMethod().getResponseBodyAsStream() == null) {
        getHttpMethod().releaseConnection();
      }
    } catch (IOException ioe) {
      this.clientHelper
          .getLogger()
          .log(
              Level.WARNING,
              "An error occurred during the communication with the remote HTTP server.",
              ioe);
      result = new Status(Status.CONNECTOR_ERROR_COMMUNICATION, ioe);

      // Release the connection
      getHttpMethod().releaseConnection();
    }

    return result;
  }
示例#11
0
  /**
   * @param since last modified time to use
   * @param req
   * @param url if null, ignored
   * @param redirCount number of redirs we've done
   */
  public static HttpData getDataOnce(
      HttpServletRequest req,
      HttpServletResponse res,
      long since,
      String surl,
      int redirCount,
      int timeout)
      throws IOException, HttpException, DataSourceException, MalformedURLException {

    HttpMethodBase request = null;
    HostConfiguration hcfg = new HostConfiguration();

    /*
      [todo hqm 2006-02-01] Anyone know why this code was here? It is setting
      the mime type to something which just confuses the DHTML parser.

      if (res != null) {
        res.setContentType("application/x-www-form-urlencoded;charset=UTF-8");
        }
    */

    try {

      // TODO: [2002-01-09 bloch] cope with cache-control
      // response headers (no-store, no-cache, must-revalidate,
      // proxy-revalidate).

      if (surl == null) {
        surl = getURL(req);
      }
      if (surl == null || surl.equals("")) {
        throw new MalformedURLException(
            /* (non-Javadoc)
             * @i18n.test
             * @org-mes="url is empty or null"
             */
            org.openlaszlo.i18n.LaszloMessages.getMessage(
                HTTPDataSource.class.getName(), "051018-312"));
      }

      String reqType = "";
      String headers = "";

      if (req != null) {
        reqType = req.getParameter("reqtype");
        headers = req.getParameter("headers");
      }

      boolean isPost = false;
      mLogger.debug("reqtype = " + reqType);

      if (reqType != null && reqType.equals("POST")) {
        request = new LZPostMethod();
        request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
        isPost = true;
        mLogger.debug("setting POST req method");
      } else if (reqType != null && reqType.equals("PUT")) {
        request = new LZPutMethod();
        // todo [hqm 2007] treat PUT like POST?
        isPost = true;
        mLogger.debug("setting PUT req method");
      } else if (reqType != null && reqType.equals("DELETE")) {
        request = new LZDeleteMethod();
        mLogger.debug("setting DELETE req method");
      } else {
        mLogger.debug("setting GET (default) req method");
        request = new LZGetMethod();
      }

      request.setHttp11(mUseHttp11);

      // Proxy the request headers
      if (req != null) {
        LZHttpUtils.proxyRequestHeaders(req, request);
      }

      // Set headers from query string
      if (headers != null && headers.length() > 0) {
        StringTokenizer st = new StringTokenizer(headers, "\n");
        while (st.hasMoreTokens()) {
          String h = st.nextToken();
          int i = h.indexOf(":");
          if (i > -1) {
            String n = h.substring(0, i);
            String v = h.substring(i + 2, h.length());
            request.setRequestHeader(n, v);
            mLogger.debug(
                /* (non-Javadoc)
                 * @i18n.test
                 * @org-mes="setting header " + p[0] + "=" + p[1]
                 */
                org.openlaszlo.i18n.LaszloMessages.getMessage(
                    HTTPDataSource.class.getName(), "051018-359", new Object[] {n, v}));
          }
        }
      }

      mLogger.debug("Parsing url");
      URI uri = LZHttpUtils.newURI(surl);
      try {
        hcfg.setHost(uri);
      } catch (Exception e) {
        throw new MalformedURLException(
            /* (non-Javadoc)
             * @i18n.test
             * @org-mes="can't form uri from " + p[0]
             */
            org.openlaszlo.i18n.LaszloMessages.getMessage(
                HTTPDataSource.class.getName(), "051018-376", new Object[] {surl}));
      }

      // This gets us the url-encoded (escaped) path and query string
      String path = uri.getEscapedPath();
      String query = uri.getEscapedQuery();
      mLogger.debug(
          /* (non-Javadoc)
           * @i18n.test
           * @org-mes="encoded path:  " + p[0]
           */
          org.openlaszlo.i18n.LaszloMessages.getMessage(
              HTTPDataSource.class.getName(), "051018-389", new Object[] {path}));
      mLogger.debug(
          /* (non-Javadoc)
           * @i18n.test
           * @org-mes="encoded query: " + p[0]
           */
          org.openlaszlo.i18n.LaszloMessages.getMessage(
              HTTPDataSource.class.getName(), "051018-397", new Object[] {query}));

      // This call takes a decoded (unescaped) path
      request.setPath(path);

      boolean hasQuery = (query != null && query.length() > 0);

      String rawcontent = null;
      // Newer rawpost protocol puts lzpostbody as a separate
      // top level query arg in the request.
      rawcontent = req.getParameter("lzpostbody");

      if (isPost) {
        // Older rawpost protocol put the "lzpostbody" arg
        // embedded in the "url" args's query args
        if (rawcontent == null && hasQuery) {
          rawcontent = findQueryArg("lzpostbody", query);
        }
        if (rawcontent != null) {
          // Get the unescaped query string
          ((EntityEnclosingMethod) request).setRequestBody(rawcontent);
        } else if (hasQuery) {
          StringTokenizer st = new StringTokenizer(query, "&");
          while (st.hasMoreTokens()) {
            String it = st.nextToken();
            int i = it.indexOf("=");
            if (i > 0) {
              String n = it.substring(0, i);
              String v = it.substring(i + 1, it.length());
              // POST encodes values during request
              ((PostMethod) request).addParameter(n, URLDecoder.decode(v, "UTF-8"));
            } else {
              mLogger.warn(
                  /* (non-Javadoc)
                   * @i18n.test
                   * @org-mes="ignoring bad token (missing '=' char) in query string: " + p[0]
                   */
                  org.openlaszlo.i18n.LaszloMessages.getMessage(
                      HTTPDataSource.class.getName(), "051018-429", new Object[] {it}));
            }
          }
        }
      } else {
        // This call takes an encoded (escaped) query string
        request.setQueryString(query);
      }

      // Put in the If-Modified-Since headers
      if (since != -1) {
        String lms = LZHttpUtils.getDateString(since);
        request.setRequestHeader(LZHttpUtils.IF_MODIFIED_SINCE, lms);
        mLogger.debug(
            /* (non-Javadoc)
             * @i18n.test
             * @org-mes="proxying lms: " + p[0]
             */
            org.openlaszlo.i18n.LaszloMessages.getMessage(
                HTTPDataSource.class.getName(), "051018-450", new Object[] {lms}));
      }

      mLogger.debug(
          /* (non-Javadoc)
           * @i18n.test
           * @org-mes="setting up http client"
           */
          org.openlaszlo.i18n.LaszloMessages.getMessage(
              HTTPDataSource.class.getName(), "051018-460"));
      HttpClient htc = null;
      if (mConnectionMgr != null) {
        htc = new HttpClient(mConnectionMgr);
      } else {
        htc = new HttpClient();
      }

      htc.setHostConfiguration(hcfg);

      // This is the data timeout
      mLogger.debug(
          /* (non-Javadoc)
           * @i18n.test
           * @org-mes="timeout set to " + p[0]
           */
          org.openlaszlo.i18n.LaszloMessages.getMessage(
              HTTPDataSource.class.getName(), "051018-478", new Object[] {new Integer(timeout)}));
      htc.setTimeout(timeout);

      // Set connection timeout the same
      htc.setConnectionTimeout(mConnectionTimeout);

      // Set timeout for getting a connection
      htc.setHttpConnectionFactoryTimeout(mConnectionPoolTimeout);

      // TODO: [2003-03-05 bloch] this should be more configurable (per app?)
      if (!isPost) {
        request.setFollowRedirects(mFollowRedirects > 0);
      }

      long t1 = System.currentTimeMillis();
      mLogger.debug("starting remote request");
      int rc = htc.executeMethod(hcfg, request);
      String status = HttpStatus.getStatusText(rc);
      if (status == null) {
        status = "" + rc;
      }
      mLogger.debug(
          /* (non-Javadoc)
           * @i18n.test
           * @org-mes="remote response status: " + p[0]
           */
          org.openlaszlo.i18n.LaszloMessages.getMessage(
              HTTPDataSource.class.getName(), "051018-504", new Object[] {status}));

      HttpData data = null;
      if (isRedirect(rc) && mFollowRedirects > redirCount) {
        String loc = request.getResponseHeader("Location").toString();
        String hostURI = loc.substring(loc.indexOf(": ") + 2, loc.length());
        mLogger.info(
            /* (non-Javadoc)
             * @i18n.test
             * @org-mes="Following URL from redirect: " + p[0]
             */
            org.openlaszlo.i18n.LaszloMessages.getMessage(
                HTTPDataSource.class.getName(), "051018-517", new Object[] {hostURI}));
        long t2 = System.currentTimeMillis();
        if (timeout > 0) {
          timeout -= (t2 - t1);
          if (timeout < 0) {
            throw new InterruptedIOException(
                /* (non-Javadoc)
                 * @i18n.test
                 * @org-mes=p[0] + " timed out after redirecting to " + p[1]
                 */
                org.openlaszlo.i18n.LaszloMessages.getMessage(
                    HTTPDataSource.class.getName(), "051018-529", new Object[] {surl, loc}));
          }
        }

        data = getDataOnce(req, res, since, hostURI, redirCount++, timeout);
      } else {
        data = new HttpData(request, rc);
      }

      if (req != null && res != null) {
        // proxy response headers
        LZHttpUtils.proxyResponseHeaders(request, res, req.isSecure());
      }

      return data;

    } catch (ConnectTimeoutException ce) {
      // Transduce to an InterrupedIOException, since lps takes these to be timeouts.
      if (request != null) {
        request.releaseConnection();
      }
      throw new InterruptedIOException(
          /* (non-Javadoc)
           * @i18n.test
           * @org-mes="connecting to " + p[0] + ":" + p[1] + " timed out beyond " + p[2] + " msecs."
           */
          org.openlaszlo.i18n.LaszloMessages.getMessage(
              HTTPDataSource.class.getName(),
              "051018-557",
              new Object[] {
                hcfg.getHost(), new Integer(hcfg.getPort()), new Integer(mConnectionTimeout)
              }));
    } catch (HttpRecoverableException hre) {
      if (request != null) {
        request.releaseConnection();
      }
      throw hre;
    } catch (HttpException e) {
      if (request != null) {
        request.releaseConnection();
      }
      throw e;
    } catch (IOException ie) {
      if (request != null) {
        request.releaseConnection();
      }
      throw ie;
    } catch (RuntimeException e) {
      if (request != null) {
        request.releaseConnection();
      }
      throw e;
    }
  }
示例#12
0
  @Test
  public void testAsyncRangeRequests()
      throws IOException, URISyntaxException, InterruptedException {
    final URL testResourceUrl = new URL(VAULT_BASE_URI.toURL(), "asyncRangeRequestTestFile.txt");

    final MultiThreadedHttpConnectionManager cm = new MultiThreadedHttpConnectionManager();
    cm.getParams().setDefaultMaxConnectionsPerHost(50);
    final HttpClient client = new HttpClient(cm);

    // prepare 8MiB test data:
    final byte[] plaintextData = new byte[2097152 * Integer.BYTES];
    final ByteBuffer bbIn = ByteBuffer.wrap(plaintextData);
    for (int i = 0; i < 2097152; i++) {
      bbIn.putInt(i);
    }

    // put request:
    final EntityEnclosingMethod putMethod = new PutMethod(testResourceUrl.toString());
    putMethod.setRequestEntity(new ByteArrayRequestEntity(plaintextData));
    final int putResponse = client.executeMethod(putMethod);
    putMethod.releaseConnection();
    Assert.assertEquals(201, putResponse);

    // multiple async range requests:
    final List<ForkJoinTask<?>> tasks = new ArrayList<>();
    final Random generator = new Random(System.currentTimeMillis());

    final AtomicBoolean success = new AtomicBoolean(true);

    // 10 full interrupted requests:
    for (int i = 0; i < 10; i++) {
      final ForkJoinTask<?> task =
          ForkJoinTask.adapt(
              () -> {
                try {
                  final HttpMethod getMethod = new GetMethod(testResourceUrl.toString());
                  final int statusCode = client.executeMethod(getMethod);
                  if (statusCode != 200) {
                    LOG.error("Invalid status code for interrupted full request");
                    success.set(false);
                  }
                  getMethod.getResponseBodyAsStream().read();
                  getMethod.getResponseBodyAsStream().close();
                  getMethod.releaseConnection();
                } catch (IOException e) {
                  throw new RuntimeException(e);
                }
              });
      tasks.add(task);
    }

    // 50 crappy interrupted range requests:
    for (int i = 0; i < 50; i++) {
      final int lower = generator.nextInt(plaintextData.length);
      final ForkJoinTask<?> task =
          ForkJoinTask.adapt(
              () -> {
                try {
                  final HttpMethod getMethod = new GetMethod(testResourceUrl.toString());
                  getMethod.addRequestHeader("Range", "bytes=" + lower + "-");
                  final int statusCode = client.executeMethod(getMethod);
                  if (statusCode != 206) {
                    LOG.error("Invalid status code for interrupted range request");
                    success.set(false);
                  }
                  getMethod.getResponseBodyAsStream().read();
                  getMethod.getResponseBodyAsStream().close();
                  getMethod.releaseConnection();
                } catch (IOException e) {
                  throw new RuntimeException(e);
                }
              });
      tasks.add(task);
    }

    // 50 normal open range requests:
    for (int i = 0; i < 50; i++) {
      final int lower = generator.nextInt(plaintextData.length - 512);
      final int upper = plaintextData.length - 1;
      final ForkJoinTask<?> task =
          ForkJoinTask.adapt(
              () -> {
                try {
                  final HttpMethod getMethod = new GetMethod(testResourceUrl.toString());
                  getMethod.addRequestHeader("Range", "bytes=" + lower + "-");
                  final byte[] expected = Arrays.copyOfRange(plaintextData, lower, upper + 1);
                  final int statusCode = client.executeMethod(getMethod);
                  final byte[] responseBody = new byte[upper - lower + 10];
                  final int bytesRead =
                      IOUtils.read(getMethod.getResponseBodyAsStream(), responseBody);
                  getMethod.releaseConnection();
                  if (statusCode != 206) {
                    LOG.error("Invalid status code for open range request");
                    success.set(false);
                  } else if (upper - lower + 1 != bytesRead) {
                    LOG.error("Invalid response length for open range request");
                    success.set(false);
                  } else if (!Arrays.equals(
                      expected, Arrays.copyOfRange(responseBody, 0, bytesRead))) {
                    LOG.error("Invalid response body for open range request");
                    success.set(false);
                  }
                } catch (IOException e) {
                  throw new RuntimeException(e);
                }
              });
      tasks.add(task);
    }

    // 200 normal closed range requests:
    for (int i = 0; i < 200; i++) {
      final int pos1 = generator.nextInt(plaintextData.length - 512);
      final int pos2 = pos1 + 512;
      final ForkJoinTask<?> task =
          ForkJoinTask.adapt(
              () -> {
                try {
                  final int lower = Math.min(pos1, pos2);
                  final int upper = Math.max(pos1, pos2);
                  final HttpMethod getMethod = new GetMethod(testResourceUrl.toString());
                  getMethod.addRequestHeader("Range", "bytes=" + lower + "-" + upper);
                  final byte[] expected = Arrays.copyOfRange(plaintextData, lower, upper + 1);
                  final int statusCode = client.executeMethod(getMethod);
                  final byte[] responseBody = new byte[upper - lower + 1];
                  final int bytesRead =
                      IOUtils.read(getMethod.getResponseBodyAsStream(), responseBody);
                  getMethod.releaseConnection();
                  if (statusCode != 206) {
                    LOG.error("Invalid status code for closed range request");
                    success.set(false);
                  } else if (upper - lower + 1 != bytesRead) {
                    LOG.error("Invalid response length for closed range request");
                    success.set(false);
                  } else if (!Arrays.equals(
                      expected, Arrays.copyOfRange(responseBody, 0, bytesRead))) {
                    LOG.error("Invalid response body for closed range request");
                    success.set(false);
                  }
                } catch (IOException e) {
                  throw new RuntimeException(e);
                }
              });
      tasks.add(task);
    }

    Collections.shuffle(tasks, generator);

    final ForkJoinPool pool = new ForkJoinPool(4);
    for (ForkJoinTask<?> task : tasks) {
      pool.execute(task);
    }
    for (ForkJoinTask<?> task : tasks) {
      task.join();
    }
    pool.shutdown();
    cm.shutdown();

    Assert.assertTrue(success.get());
  }
  @Override
  public void executeMethod(final HttpMethod method, final ClientRequest cr) {
    final Map<String, Object> props = cr.getProperties();

    method.setDoAuthentication(true);

    final HttpMethodParams methodParams = method.getParams();

    // Set the handle cookies property
    if (!cr.getPropertyAsFeature(ApacheHttpClientConfig.PROPERTY_HANDLE_COOKIES)) {
      methodParams.setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
    }

    // Set the interactive and credential provider properties
    if (cr.getPropertyAsFeature(ApacheHttpClientConfig.PROPERTY_INTERACTIVE)) {
      CredentialsProvider provider =
          (CredentialsProvider) props.get(ApacheHttpClientConfig.PROPERTY_CREDENTIALS_PROVIDER);
      if (provider == null) {
        provider = DEFAULT_CREDENTIALS_PROVIDER;
      }
      methodParams.setParameter(CredentialsProvider.PROVIDER, provider);
    } else {
      methodParams.setParameter(CredentialsProvider.PROVIDER, null);
    }

    // Set the read timeout
    final Integer readTimeout = (Integer) props.get(ApacheHttpClientConfig.PROPERTY_READ_TIMEOUT);
    if (readTimeout != null) {
      methodParams.setSoTimeout(readTimeout);
    }

    if (method instanceof EntityEnclosingMethod) {
      final EntityEnclosingMethod entMethod = (EntityEnclosingMethod) method;

      if (cr.getEntity() != null) {
        final RequestEntityWriter re = getRequestEntityWriter(cr);
        final Integer chunkedEncodingSize =
            (Integer) props.get(ApacheHttpClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE);
        if (chunkedEncodingSize != null) {
          // There doesn't seems to be a way to set the chunk size.
          entMethod.setContentChunked(true);

          // It is not possible for a MessageBodyWriter to modify
          // the set of headers before writing out any bytes to
          // the OutputStream
          // This makes it impossible to use the multipart
          // writer that modifies the content type to add a boundary
          // parameter
          writeOutBoundHeaders(cr.getHeaders(), method);

          // Do not buffer the request entity when chunked encoding is
          // set
          entMethod.setRequestEntity(
              new RequestEntity() {

                @Override
                public boolean isRepeatable() {
                  return false;
                }

                @Override
                public void writeRequest(OutputStream out) throws IOException {
                  re.writeRequestEntity(out);
                }

                @Override
                public long getContentLength() {
                  return re.getSize();
                }

                @Override
                public String getContentType() {
                  return re.getMediaType().toString();
                }
              });

        } else {
          entMethod.setContentChunked(false);

          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          try {
            re.writeRequestEntity(
                new CommittingOutputStream(baos) {

                  @Override
                  protected void commit() throws IOException {
                    writeOutBoundHeaders(cr.getMetadata(), method);
                  }
                });
          } catch (IOException ex) {
            throw new ClientHandlerException(ex);
          }

          final byte[] content = baos.toByteArray();
          entMethod.setRequestEntity(
              new RequestEntity() {

                @Override
                public boolean isRepeatable() {
                  return true;
                }

                @Override
                public void writeRequest(OutputStream out) throws IOException {
                  out.write(content);
                }

                @Override
                public long getContentLength() {
                  return content.length;
                }

                @Override
                public String getContentType() {
                  return re.getMediaType().toString();
                }
              });
        }
      }
    } else {
      writeOutBoundHeaders(cr.getHeaders(), method);

      // Follow redirects
      method.setFollowRedirects(
          cr.getPropertyAsFeature(ApacheHttpClientConfig.PROPERTY_FOLLOW_REDIRECTS));
    }
    try {
      httpClient.executeMethod(
          getHostConfiguration(httpClient, props), method, getHttpState(props));
    } catch (Exception e) {
      method.releaseConnection();
      throw new ClientHandlerException(e);
    }
  }
  protected byte[] URLtoByteArray(
      String location,
      Http.Method method,
      Map<String, String> headers,
      Cookie[] cookies,
      Http.Auth auth,
      Http.Body body,
      List<Http.FilePart> fileParts,
      Map<String, String> parts,
      Http.Response response,
      boolean followRedirects)
      throws IOException {

    byte[] bytes = null;

    HttpMethod httpMethod = null;
    HttpState httpState = null;

    try {
      _cookies.set(null);

      if (location == null) {
        return null;
      } else if (!location.startsWith(Http.HTTP_WITH_SLASH)
          && !location.startsWith(Http.HTTPS_WITH_SLASH)) {

        location = Http.HTTP_WITH_SLASH + location;
      }

      HostConfiguration hostConfiguration = getHostConfiguration(location);

      HttpClient httpClient = getClient(hostConfiguration);

      if (method.equals(Http.Method.POST) || method.equals(Http.Method.PUT)) {

        if (method.equals(Http.Method.POST)) {
          httpMethod = new PostMethod(location);
        } else {
          httpMethod = new PutMethod(location);
        }

        if (body != null) {
          RequestEntity requestEntity =
              new StringRequestEntity(body.getContent(), body.getContentType(), body.getCharset());

          EntityEnclosingMethod entityEnclosingMethod = (EntityEnclosingMethod) httpMethod;

          entityEnclosingMethod.setRequestEntity(requestEntity);
        } else if (method.equals(Http.Method.POST)) {
          PostMethod postMethod = (PostMethod) httpMethod;

          processPostMethod(postMethod, fileParts, parts);
        }
      } else if (method.equals(Http.Method.DELETE)) {
        httpMethod = new DeleteMethod(location);
      } else if (method.equals(Http.Method.HEAD)) {
        httpMethod = new HeadMethod(location);
      } else {
        httpMethod = new GetMethod(location);
      }

      if (headers != null) {
        for (Map.Entry<String, String> header : headers.entrySet()) {
          httpMethod.addRequestHeader(header.getKey(), header.getValue());
        }
      }

      if ((method.equals(Http.Method.POST) || method.equals(Http.Method.PUT))
          && ((body != null)
              || ((fileParts != null) && !fileParts.isEmpty())
                  | ((parts != null) && !parts.isEmpty()))) {
      } else if (!hasRequestHeader(httpMethod, HttpHeaders.CONTENT_TYPE)) {
        httpMethod.addRequestHeader(
            HttpHeaders.CONTENT_TYPE, ContentTypes.APPLICATION_X_WWW_FORM_URLENCODED);
      }

      if (!hasRequestHeader(httpMethod, HttpHeaders.USER_AGENT)) {
        httpMethod.addRequestHeader(HttpHeaders.USER_AGENT, _DEFAULT_USER_AGENT);
      }

      httpState = new HttpState();

      if ((cookies != null) && (cookies.length > 0)) {
        org.apache.commons.httpclient.Cookie[] commonsCookies = toCommonsCookies(cookies);

        httpState.addCookies(commonsCookies);

        HttpMethodParams httpMethodParams = httpMethod.getParams();

        httpMethodParams.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
      }

      if (auth != null) {
        httpMethod.setDoAuthentication(true);

        httpState.setCredentials(
            new AuthScope(auth.getHost(), auth.getPort(), auth.getRealm()),
            new UsernamePasswordCredentials(auth.getUsername(), auth.getPassword()));
      }

      proxifyState(httpState, hostConfiguration);

      httpClient.executeMethod(hostConfiguration, httpMethod, httpState);

      Header locationHeader = httpMethod.getResponseHeader("location");

      if ((locationHeader != null) && !locationHeader.equals(location)) {
        String redirect = locationHeader.getValue();

        if (followRedirects) {
          return URLtoByteArray(
              redirect,
              Http.Method.GET,
              headers,
              cookies,
              auth,
              body,
              fileParts,
              parts,
              response,
              followRedirects);
        } else {
          response.setRedirect(redirect);
        }
      }

      InputStream inputStream = httpMethod.getResponseBodyAsStream();

      if (inputStream != null) {
        Header contentLength = httpMethod.getResponseHeader(HttpHeaders.CONTENT_LENGTH);

        if (contentLength != null) {
          response.setContentLength(GetterUtil.getInteger(contentLength.getValue()));
        }

        Header contentType = httpMethod.getResponseHeader(HttpHeaders.CONTENT_TYPE);

        if (contentType != null) {
          response.setContentType(contentType.getValue());
        }

        bytes = FileUtil.getBytes(inputStream);
      }

      for (Header header : httpMethod.getResponseHeaders()) {
        response.addHeader(header.getName(), header.getValue());
      }

      return bytes;
    } finally {
      try {
        if (httpState != null) {
          _cookies.set(toServletCookies(httpState.getCookies()));
        }
      } catch (Exception e) {
        _log.error(e, e);
      }

      try {
        if (httpMethod != null) {
          httpMethod.releaseConnection();
        }
      } catch (Exception e) {
        _log.error(e, e);
      }
    }
  }