Ejemplo n.º 1
0
  /**
   * Executes a method with the current hostConfiguration.
   *
   * @throws IOException if an I/O (transport) error occurs. Some transport exceptions can be
   *     recovered from.
   * @throws HttpException if a protocol exception occurs. Usually protocol exceptions cannot be
   *     recovered from.
   */
  private void executeWithRetry(final HttpMethod method) throws IOException, HttpException {

    /** How many times did this transparently handle a recoverable exception? */
    int execCount = 0;
    // loop until the method is successfully processed, the retryHandler
    // returns false or a non-recoverable exception is thrown
    try {
      while (true) {
        execCount++;
        try {

          if (LOG.isTraceEnabled()) {
            LOG.trace("Attempt number " + execCount + " to process request");
          }
          if (this.conn.getParams().isStaleCheckingEnabled()) {
            this.conn.closeIfStale();
          }
          if (!this.conn.isOpen()) {
            // this connection must be opened before it can be used
            // This has nothing to do with opening a secure tunnel
            this.conn.open();
            if (this.conn.isProxied()
                && this.conn.isSecure()
                && !(method instanceof ConnectMethod)) {
              // we need to create a secure tunnel before we can execute the real method
              if (!executeConnect()) {
                // abort, the connect method failed
                return;
              }
            }
          }
          applyConnectionParams(method);
          method.execute(state, this.conn);
          break;
        } catch (HttpException e) {
          // filter out protocol exceptions which cannot be recovered from
          throw e;
        } catch (IOException e) {
          LOG.debug("Closing the connection.");
          this.conn.close();
          // test if this method should be retried
          // ========================================
          // this code is provided for backward compatibility with 2.0
          // will be removed in the next major release
          if (method instanceof HttpMethodBase) {
            MethodRetryHandler handler = ((HttpMethodBase) method).getMethodRetryHandler();
            if (handler != null) {
              if (!handler.retryMethod(
                  method,
                  this.conn,
                  new HttpRecoverableException(e.getMessage()),
                  execCount,
                  method.isRequestSent())) {
                LOG.debug(
                    "Method retry handler returned false. "
                        + "Automatic recovery will not be attempted");
                throw e;
              }
            }
          }
          // ========================================
          HttpMethodRetryHandler handler =
              (HttpMethodRetryHandler)
                  method.getParams().getParameter(HttpMethodParams.RETRY_HANDLER);
          if (handler == null) {
            handler = new DefaultHttpMethodRetryHandler();
          }
          if (!handler.retryMethod(method, e, execCount)) {
            LOG.debug(
                "Method retry handler returned false. "
                    + "Automatic recovery will not be attempted");
            throw e;
          }
          if (LOG.isInfoEnabled()) {
            LOG.info(
                "I/O exception ("
                    + e.getClass().getName()
                    + ") caught when processing request: "
                    + e.getMessage());
          }
          if (LOG.isDebugEnabled()) {
            LOG.debug(e.getMessage(), e);
          }
          LOG.info("Retrying request");
        }
      }
    } catch (IOException e) {
      if (this.conn.isOpen()) {
        LOG.debug("Closing the connection.");
        this.conn.close();
      }
      releaseConnection = true;
      throw e;
    } catch (RuntimeException e) {
      if (this.conn.isOpen()) {
        LOG.debug("Closing the connection.");
        this.conn.close();
      }
      releaseConnection = true;
      throw e;
    }
  }