Пример #1
0
    /**
     * Construct a connection to the specified url. A cache of
     * HTTPConnections is used to maximize the reuse of these across
     * multiple HttpURLConnections.
     *
     * <BR>The default method is "GET".
     *
     * @param url the url of the request
     * @exception ProtocolNotSuppException if the protocol is not supported
     */
    public HttpURLConnection(URL url)
	    throws ProtocolNotSuppException, IOException
    {
	super(url);

	// first read proxy properties and set
        try
        {
            String hosts = System.getProperty("http.nonProxyHosts", "");
	    if (!hosts.equalsIgnoreCase(non_proxy_hosts))
	    {
		connections.clear();
		non_proxy_hosts = hosts;
		String[] list = Util.splitProperty(hosts);
		for (int idx=0; idx<list.length; idx++)
		    HTTPConnection.dontProxyFor(list[idx]);
	    }
        }
        catch (ParseException pe)
	    { throw new IOException(pe.toString()); }
        catch (SecurityException se)
            { }

	try
	{
	    String host = System.getProperty("http.proxyHost", "");
	    int port = Integer.getInteger("http.proxyPort", -1).intValue();
	    if (!host.equalsIgnoreCase(proxy_host)  ||  port != proxy_port)
	    {
		connections.clear();
		proxy_host = host;
		proxy_port = port;
		HTTPConnection.setProxyServer(host, port);
	    }
	}
	catch (SecurityException se)
	    { }

	// now setup stuff
	con           = getConnection(url);
	method        = "GET";
	method_set    = false;
	resource      = url.getFile();
	headers       = default_headers;
	do_redir      = getFollowRedirects();
	output_stream = null;

	urlString     = url.toString();
    }
Пример #2
0
  private static void saveCookies() {
    if (cookie_jar != null
        && (!cookie_jar.exists() || cookie_jar.isFile() && cookie_jar.canWrite())) {
      Hashtable cookie_list = new Hashtable();
      Enumeration en =
          Util.getList(cookie_cntxt_list, HTTPConnection.getDefaultContext()).elements();

      // discard cookies which are not to be kept across sessions

      while (en.hasMoreElements()) {
        Cookie cookie = (Cookie) en.nextElement();
        if (!cookie.discard()) cookie_list.put(cookie, cookie);
      }

      // save any remaining cookies in jar
      if (cookie_list.size() > 0) {
        try {
          ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(cookie_jar));
          oos.writeObject(cookie_list);
          oos.close();
        } catch (IOException t) {
          if (LOG.isTraceEnabled()) {
            LOG.trace("An exception occurred: " + t.getMessage());
          }
        }
      }
    }
  }
  /** Loads detailed tax payer info */
  public void loadInfo() {
    // try to connect
    try {

      // Get TaxPayer Income first:
      HTTPConnection connection = new HTTPConnection(storage.getServerURL());

      JSONObject response = connection.connectJSON(Engine.getTaxPayerInfo(TaxPayerID));
      storage.setLastServerResponse(response.toString());

      if (!response.getString("result").equals("OK")) {
        throw new Exception("Invalid response from server = " + response.getString("data"));
      }

      // read results
      JSONObject data = response.getJSONArray("data").getJSONObject(0);

      // Fill the activity with results
      TaxIncome = data.getDouble("Income");
      tbTaxYearIncome.setText(String.valueOf(TaxIncome) + " \u20AC");
      // Get Tax stats:

      response = connection.connectJSON(Engine.TaxProgramGrid(TaxYearID, TaxPayerID));
      storage.setLastServerResponse(response.toString());

      // retrieve the array of items
      array = response.getJSONArray("data");

      recalculateTaxRate();

      // only after array is loaded - show the list
      adapter = new TaxYearProgramsAdapter(this);
      tableTaxProgramManage.setAdapter(adapter);

    } catch (Exception ex) {
      DKDialog.ShowMessage(
          this,
          Translate.translate("Error"),
          Translate.translate("Connection failed: " + ex.getMessage()),
          Translate.translate("OK"),
          Translate.translate("Cancel"));

      LogWriter.writeException(this, ex.getMessage(), ex);

      storage.setLastServerResponse(ex.toString());
    }
  }
Пример #4
0
  /**
   * Update the permanent redirection list.
   *
   * @param the original request
   * @param the new location
   */
  private static void update_perm_redir_list(RoRequest req, URI new_loc) {
    HTTPConnection con = req.getConnection();
    URI cur_loc = null;
    try {
      cur_loc =
          new URI(
              new URI(con.getProtocol(), con.getHost(), con.getPort(), null), req.getRequestURI());
    } catch (ParseException pe) {
      if (LOG.isTraceEnabled()) {
        LOG.trace("An exception occurred: " + pe.getMessage());
      }
    }

    if (cur_loc != null && !cur_loc.equals(new_loc)) {
      Hashtable perm_redir_list = Util.getList(perm_redir_cntxt_list, con.getContext());
      perm_redir_list.put(cur_loc, new_loc);
    }
  }
  protected void respondAdmin(HttpServletRequest req, HttpServletResponse res) throws IOException {
    res.setContentType("text/xml");
    StringBuffer buf = new StringBuffer();

    String _details = req.getParameter("details");
    boolean details = (_details != null && _details.equals("1"));

    ConnectionGroup.dumpGroupsXML(buf, details);

    String appName = req.getParameter("application");
    if (appName != null && !appName.equals("")) {
      if (appName.equals("*")) {
        Application.dumpApplicationsXML(buf, details);
      } else {
        Application application = Application.getApplication(appName, false);
        if (application != null) application.toString();
      }
    }

    ConnectionAgent.dumpAgentsXML(buf, details);

    ServletOutputStream out = res.getOutputStream();
    try {
      out.println(
          "<connection-info "
              + " max-message-length=\""
              + HTTPConnection.getMaxMessageLen()
              + "\""
              + " connection-length=\""
              + HTTPConnection.getConnectionLength()
              + "\""
              + " reconnection-wait-interval=\""
              + HTTPConnection.getReconnectionWaitInterval()
              + "\""
              + " >");
      out.println(buf.toString());
      out.println("</connection-info>");
    } finally {
      FileUtils.close(out);
    }
  }
 private static void loadCookies() {
   // The isFile() etc need to be protected by the catch as signed
   // applets may be allowed to read properties but not do IO
   try {
     cookie_jar = new File(getCookieJarName());
     if (cookie_jar.isFile() && cookie_jar.canRead()) {
       ObjectInputStream ois = new ObjectInputStream(new FileInputStream(cookie_jar));
       cookie_cntxt_list.put(HTTPConnection.getDefaultContext(), (Hashtable) ois.readObject());
       ois.close();
     }
   } catch (Throwable t) {
     cookie_jar = null;
   }
 }
Пример #7
0
  /** Invoked by the HTTPClient. */
  public int requestHandler(Request req, Response[] resp) {
    HTTPConnection con = req.getConnection();
    URI new_loc, cur_loc;

    // check for retries

    HttpOutputStream out = req.getStream();
    if (out != null && deferred_redir_list.get(out) != null) {
      copyFrom((RedirectionModule) deferred_redir_list.remove(out));
      req.copyFrom(saved_req);

      if (new_con) return REQ_NEWCON_RST;
      else return REQ_RESTART;
    }

    // handle permanent redirections

    try {
      cur_loc =
          new URI(
              new URI(con.getProtocol(), con.getHost(), con.getPort(), null), req.getRequestURI());
    } catch (ParseException pe) {
      throw new Error("HTTPClient Internal Error: unexpected exception '" + pe + "'", pe);
    }

    // handle permanent redirections

    Hashtable perm_redir_list =
        Util.getList(perm_redir_cntxt_list, req.getConnection().getContext());
    if ((new_loc = (URI) perm_redir_list.get(cur_loc)) != null) {
      /*
       * copy query if present in old url but not in new url. This isn't
       * strictly conforming, but some scripts fail to properly propagate the
       * query string to the Location header. Unfortunately it looks like we're
       * f****d either way: some scripts fail if you don't propagate the query
       * string, some fail if you do... God, don't you just love it when people
       * can't read a spec? Anway, since we can't get it right for all scripts
       * we opt to follow the spec. String nres = new_loc.getPathAndQuery(),
       * oquery = Util.getQuery(req.getRequestURI()), nquery =
       * Util.getQuery(nres); if (nquery == null && oquery != null) nres += "?"
       * + oquery;
       */
      String nres = new_loc.getPathAndQuery();
      req.setRequestURI(nres);

      try {
        lastURI = new URI(new_loc, nres);
      } catch (ParseException pe) {
        if (LOG.isTraceEnabled()) {
          LOG.trace("An exception occurred: " + pe.getMessage());
        }
      }

      if (LOG.isDebugEnabled())
        LOG.debug(
            "Matched request in permanent redirection list - redoing request to "
                + lastURI.toExternalForm());

      if (!con.isCompatibleWith(new_loc)) {
        try {
          con = new HTTPConnection(new_loc);
        } catch (ProtocolNotSuppException e) {
          throw new Error("HTTPClient Internal Error: unexpected " + "exception '" + e + "'", e);
        }

        con.setContext(req.getConnection().getContext());
        req.setConnection(con);
        return REQ_NEWCON_RST;
      } else {
        return REQ_RESTART;
      }
    }

    return REQ_CONTINUE;
  }
Пример #8
0
  /** Invoked by the HTTPClient. */
  public int responsePhase2Handler(Response resp, Request req) throws IOException {
    /* handle various response status codes until satisfied */

    int sts = resp.getStatusCode();
    switch (sts) {
      case 302: // General (temporary) Redirection (handle like 303)

        /*
         * Note we only do this munging for POST and PUT. For GET it's not
         * necessary; for HEAD we probably want to do another HEAD. For all
         * others (i.e. methods from WebDAV, IPP, etc) it's somewhat unclear -
         * servers supporting those should really return a 307 or 303, but some
         * don't (guess who...), so we just don't touch those.
         */
        if (req.getMethod().equals("POST") || req.getMethod().equals("PUT")) {
          if (LOG.isDebugEnabled())
            LOG.debug(
                "Received status: " + sts + " " + resp.getReasonLine() + " - treating as 303");

          sts = 303;
        }

      case 301: // Moved Permanently
      case 303: // See Other (use GET)
      case 307: // Moved Temporarily (we mean it!)
        if (LOG.isDebugEnabled()) LOG.debug("Handling status: " + sts + " " + resp.getReasonLine());

        // the spec says automatic redirection may only be done if
        // the second request is a HEAD or GET.
        if (!req.getMethod().equals("GET") && !req.getMethod().equals("HEAD") && sts != 303) {
          if (LOG.isDebugEnabled())
            LOG.debug("Not redirected because method is neither HEAD nor GET");

          if (sts == 301 && resp.getHeader("Location") != null)
            update_perm_redir_list(req, resLocHdr(resp.getHeader("Location"), req));

          resp.setEffectiveURI(lastURI);
          return RSP_CONTINUE;
        }

      case 305: // Use Proxy
      case 306: // Switch Proxy
        if (sts == 305 || sts == 306) {
          if (LOG.isDebugEnabled())
            LOG.debug("Handling status: " + sts + " " + resp.getReasonLine());
        }

        // Don't accept 305 from a proxy
        if (sts == 305 && req.getConnection().getProxyHost() != null) {
          if (LOG.isDebugEnabled()) LOG.debug("305 ignored because a proxy is already in use");

          resp.setEffectiveURI(lastURI);
          return RSP_CONTINUE;
        }

        /*
         * the level is a primitive way of preventing infinite redirections.
         * RFC-2068 set the max to 5, but RFC-2616 has loosened this. Since some
         * sites (notably M$) need more levels, this is now set to the
         * (arbitrary) value of 15 (god only knows why they need to do even 5
         * redirections...).
         */
        if (level >= 15 || resp.getHeader("Location") == null) {
          if (LOG.isDebugEnabled()) {
            if (level >= 15) LOG.debug("Not redirected because of too many levels of redirection");
            else LOG.debug("Not redirected because no Location header was present");
          }

          resp.setEffectiveURI(lastURI);
          return RSP_CONTINUE;
        }
        level++;

        URI loc = resLocHdr(resp.getHeader("Location"), req);

        HTTPConnection mvd;
        String nres;
        new_con = false;

        if (sts == 305) {
          mvd =
              new HTTPConnection(
                  req.getConnection().getProtocol(),
                  req.getConnection().getHost(),
                  req.getConnection().getPort());
          mvd.setCurrentProxy(loc.getHost(), loc.getPort());
          mvd.setContext(req.getConnection().getContext());
          new_con = true;

          nres = req.getRequestURI();

          /*
           * There was some discussion about this, and especially Foteos
           * Macrides (Lynx) said a 305 should also imply a change to GET (for
           * security reasons) - see the thread starting at
           * http://www.ics.uci.edu/pub/ietf/http/hypermail/1997q4/0351.html
           * However, this is not in the latest draft, but since I agree with
           * Foteos we do it anyway...
           */
          req.setMethod("GET");
          req.setData(null);
          req.setStream(null);
        } else if (sts == 306) {
          // We'll have to wait for Josh to create a new spec here.
          return RSP_CONTINUE;
        } else {
          if (req.getConnection().isCompatibleWith(loc)) {
            mvd = req.getConnection();
            nres = loc.getPathAndQuery();
          } else {
            try {
              mvd = new HTTPConnection(loc);
              nres = loc.getPathAndQuery();
            } catch (ProtocolNotSuppException e) {
              if (req.getConnection().getProxyHost() == null
                  || !loc.getScheme().equalsIgnoreCase("ftp")) return RSP_CONTINUE;

              // We're using a proxy and the protocol is ftp -
              // maybe the proxy will also proxy ftp...
              mvd =
                  new HTTPConnection(
                      "http",
                      req.getConnection().getProxyHost(),
                      req.getConnection().getProxyPort());
              mvd.setCurrentProxy(null, 0);
              nres = loc.toExternalForm();
            }

            mvd.setContext(req.getConnection().getContext());
            new_con = true;
          }

          /*
           * copy query if present in old url but not in new url. This isn't
           * strictly conforming, but some scripts fail to propagate the query
           * properly to the Location header. See comment on line 126. String
           * oquery = Util.getQuery(req.getRequestURI()), nquery =
           * Util.getQuery(nres); if (nquery == null && oquery != null) nres +=
           * "?" + oquery;
           */

          if (sts == 303) {
            // 303 means "use GET"

            if (!req.getMethod().equals("HEAD")) req.setMethod("GET");
            req.setData(null);
            req.setStream(null);
          } else {
            // If they used an output stream then they'll have
            // to do the resend themselves
            if (req.getStream() != null) {
              if (!HTTPConnection.deferStreamed) {
                if (LOG.isDebugEnabled())
                  LOG.debug("Status " + sts + " not handled - request has an output stream");

                return RSP_CONTINUE;
              }

              saved_req = (Request) req.clone();
              deferred_redir_list.put(req.getStream(), this);
              req.getStream().reset();
              resp.setRetryRequest(true);
            }

            if (sts == 301) {
              // update permanent redirection list
              try {
                update_perm_redir_list(req, new URI(loc, nres));
              } catch (ParseException pe) {
                throw new Error(
                    "HTTPClient Internal Error: " + "unexpected exception '" + pe + "'", pe);
              }
            }
          }

          // Adjust Referer, if present
          NVPair[] hdrs = req.getHeaders();
          for (int idx = 0; idx < hdrs.length; idx++)
            if (hdrs[idx].getName().equalsIgnoreCase("Referer")) {
              HTTPConnection con = req.getConnection();
              hdrs[idx] = new NVPair("Referer", con + req.getRequestURI());
              break;
            }
        }

        req.setConnection(mvd);
        req.setRequestURI(nres);

        try {
          resp.getInputStream().close();
        } catch (IOException ioe) {
          if (LOG.isTraceEnabled()) {
            LOG.trace("An exception occurred: " + ioe.getMessage());
          }
        }

        if (sts != 305 && sts != 306) {
          try {
            lastURI = new URI(loc, nres);
          } catch (ParseException pe) {
            if (LOG.isTraceEnabled()) {
              LOG.trace("An exception occurred: " + pe.getMessage());
            }
          }

          if (LOG.isDebugEnabled())
            LOG.debug(
                "Request redirected to "
                    + lastURI.toExternalForm()
                    + " using method "
                    + req.getMethod());
        } else {
          if (LOG.isDebugEnabled())
            LOG.debug(
                "Resending request using "
                    + "proxy "
                    + mvd.getProxyHost()
                    + ":"
                    + mvd.getProxyPort());
        }

        if (req.getStream() != null) return RSP_CONTINUE;
        else if (new_con) return RSP_NEWCON_REQ;
        else return RSP_REQUEST;

      default:
        return RSP_CONTINUE;
    }
  }
    public void work() {
      // get the first institution
      if (total < _selected.size()) {
        int id = _selected.get(total);

        double firstPrice = 0;
        double currentPrice = 0;
        double avgPriceForProgram =
            (TaxIncome / _selected.size())
                * 0.2; // this is a price that is calculate for programs, average 20% of income

        // start negotiating
        try {
          // Get initial price of program
          LogWriter.writeInfo(
              "Agent -> Get program price: avgPerProgram = "
                  + avgPriceForProgram
                  + ", program ID = "
                  + id);

          HTTPConnection connection = new HTTPConnection(storage.getServerURL());

          JSONObject response =
              connection.connectJSON(Engine.AgentRequestProgramPrice(_taxYearID, _taxPayerID, id));
          storage.setLastServerResponse(response.toString());

          if (!response.getString("result").equals("OK")) {
            throw new Exception("Invalid response from server = " + response.getString("data"));
          }

          // read results
          JSONObject data = response.getJSONObject("data");

          int type = data.getInt("Type");
          currentPrice = data.getDouble("Price");
          firstPrice = currentPrice;
          double lowestPrice = firstPrice;
          double newPrice = 0;

          if (type == 1) {
            // this is final offer - we need to set the result - and offer to client
            LogWriter.writeInfo("Agent -> Final offer = " + currentPrice + " program ID = " + id);
            setProgramPrice(id, currentPrice);
          } else {
            double tries = 0.5;

            while (true) {
              if (type == 1) {
                // this is final offer - we need to set the result - and offer to client
                LogWriter.writeInfo(
                    "Agent -> Final offer = " + currentPrice + " program ID = " + id);
                setProgramPrice(id, currentPrice);
                break;
              }

              // we can try to continue more - to get a better deal if it is more than we want
              if (newPrice > firstPrice) {
                // obiously we cannot get betterp rice
                LogWriter.writeInfo(
                    "Agent -> Cannot go higher = " + lowestPrice + " program ID = " + id);
                setProgramPrice(id, lowestPrice);
                break;
              } else if (currentPrice > avgPriceForProgram) {

                // Get initial price of program
                connection = new HTTPConnection(storage.getServerURL());

                newPrice = avgPriceForProgram * 0.1 + avgPriceForProgram * (tries);

                LogWriter.writeInfo(
                    "Agent -> Askin better price = " + newPrice + " program ID = " + id);

                // lowe the price by 90%
                response =
                    connection.connectJSON(
                        Engine.AgentRequestProgramLowerPrice(
                            _taxYearID, _taxPayerID, id, newPrice));
                storage.setLastServerResponse(response.toString());

                if (!response.getString("result").equals("OK")) {
                  throw new Exception(
                      "Invalid response from server = " + response.getString("data"));
                }

                // read results
                data = response.getJSONObject("data");

                type = data.getInt("Type");
                currentPrice = data.getDouble("Price");

                LogWriter.writeInfo(
                    "Agent -> currentPrice = "
                        + currentPrice
                        + " lowestPrice = "
                        + lowestPrice
                        + " program ID = "
                        + id);

                if (currentPrice < lowestPrice) {
                  lowestPrice = currentPrice;
                }

                tries += 0.1;
              } else {
                // this is ok, we can accept that
                LogWriter.writeInfo(
                    "Agent -> Best offer = " + currentPrice + " program ID = " + id);
                setProgramPrice(id, currentPrice);
                break;
              }
            }
          }

        } catch (Exception ex) {
          // this will exit

          Message msg = mHandler.obtainMessage();
          Bundle b = new Bundle();
          b.putString("error", "Connection failed: " + ex.getMessage());
          msg.setData(b);
          mHandler.sendMessage(msg);

          LogWriter.writeException(TaxProgramsManageActivity.this, ex.getMessage(), ex);
        }
      }
    }
        public void onClick(View arg0) {

          if (btnCancel.getVisibility() == View.VISIBLE) {
            // Confirmation of existing programs

            try {

              for (int i = 0; i < array.length(); i++) {
                JSONObject object = (JSONObject) array.get(i);

                if (object.getInt("IsSelected") > 0) {
                  // Get TaxPayer Income first:
                  HTTPConnection connection = new HTTPConnection(storage.getServerURL());

                  JSONObject response =
                      connection.connectJSON(
                          Engine.ApproveProgramPrice(
                              TaxYearID,
                              TaxPayerID,
                              object.getInt("ID"),
                              object.getDouble("TaxRate")));
                  storage.setLastServerResponse(response.toString());

                  if (!response.getString("result").equals("OK")) {
                    throw new Exception(
                        "Invalid response from server = " + response.getString("data"));
                  }

                  // read results
                  int result = (Integer) response.getInt("data");
                }
              }

              Intent resultIntent = new Intent();
              setResult(Activity.RESULT_OK, resultIntent);
              TaxProgramsManageActivity.this.finish();
              /*
              	DKDialog.ShowMessage( TaxProgramsManageActivity.this,
              Translate.translate("Thank you") ,
              Translate.translate("All programs have been confirmed!"),
              Translate.translate("OK"),
              Translate.translate("Cancel"));
              	*/

            } catch (Exception ex) {
              DKDialog.ShowMessage(
                  TaxProgramsManageActivity.this,
                  Translate.translate("Error"),
                  Translate.translate("Connection failed: " + ex.getMessage()),
                  Translate.translate("OK"),
                  Translate.translate("Cancel"));

              LogWriter.writeException(TaxProgramsManageActivity.this, ex.getMessage(), ex);

              storage.setLastServerResponse(ex.toString());
            }
          } else {

            // 1-st submit

            selected = new ArrayList<Integer>();

            try {

              for (int i = 0; i < array.length(); i++) {

                JSONObject object = array.getJSONObject(i);

                if (object.getInt("IsSelected") > 0) {
                  selected.add(object.getInt("ID"));
                } else {
                  // clear the price
                  object.put("TaxRate", 0.0);
                }
              }

              if (selected.size() == 0) {
                DKDialog.ShowMessage(
                    TaxProgramsManageActivity.this,
                    Translate.translate("Error"),
                    Translate.translate("Nothing to submit, no programs selected!"),
                    Translate.translate("OK"),
                    Translate.translate("Cancel"));
              } else {
                typeBar = 1;
                showDialog(typeBar);
              }
            } catch (Exception ex) {
              DKDialog.ShowMessage(
                  TaxProgramsManageActivity.this,
                  Translate.translate("Error"),
                  Translate.translate("Failed to count selected values! " + ex.getMessage()),
                  Translate.translate("OK"),
                  Translate.translate("Cancel"));

              LogWriter.writeException(TaxProgramsManageActivity.this, ex.getMessage(), ex);
            }
          }
        }
Пример #11
0
 /**
  * Remove the specified cookie from the list of cookies in the default context. If the cookie is
  * not found in the list then this method does nothing.
  *
  * @param cookie the Cookie to remove
  * @since V0.3-1
  */
 public static void removeCookie(Cookie cookie) {
   Hashtable cookie_list = Util.getList(cookie_cntxt_list, HTTPConnection.getDefaultContext());
   cookie_list.remove(cookie);
 }
Пример #12
0
  /** Invoked by the HTTPClient. */
  public void responsePhase1Handler(Response resp, RoRequest roreq)
      throws IOException, ModuleException {
    try {
      resp.getStatusCode();
    } catch (RetryException re) {
      Log.write(Log.MODS, "RtryM: Caught RetryException");

      boolean got_lock = false;

      try {
        synchronized (re.first) {
          got_lock = true;

          // initialize idempotent sequence checking
          IdempotentSequence seq = new IdempotentSequence();
          for (RetryException e = re.first; e != null; e = e.next) seq.add(e.request);

          for (RetryException e = re.first; e != null; e = e.next) {
            Log.write(Log.MODS, "RtryM: handling exception ", e);

            Request req = e.request;
            HTTPConnection con = req.getConnection();

            /* Don't retry if either the sequence is not idempotent
             * (Sec 8.1.4 and 9.1.2), or we've already retried enough
             * times, or the headers have been read and parsed
             * already
             */
            if (!seq.isIdempotent(req)
                || (con.ServProtVersKnown
                    && con.ServerProtocolVersion >= HTTP_1_1
                    && req.num_retries > 0)
                || ((!con.ServProtVersKnown || con.ServerProtocolVersion <= HTTP_1_0)
                    && req.num_retries > 4)
                || e.response.got_headers) {
              e.first = null;
              continue;
            }

            /**
             * if an output stream was used (i.e. we don't have the data to resend) then delegate
             * the responsibility for resending to the application.
             */
            if (req.getStream() != null) {
              if (HTTPConnection.deferStreamed) {
                req.getStream().reset();
                e.response.setRetryRequest(true);
              }
              e.first = null;
              continue;
            }

            /* If we have an entity then setup either the entity-delay
             * or the Expect header
             */
            if (req.getData() != null && e.conn_reset) {
              if (con.ServProtVersKnown && con.ServerProtocolVersion >= HTTP_1_1)
                addToken(req, "Expect", "100-continue");
              else req.delay_entity = 5000L << req.num_retries;
            }

            /* If the next request in line has an entity and we're
             * talking to an HTTP/1.0 server then close the socket
             * after this request. This is so that the available()
             * call (to watch for an error response from the server)
             * will work correctly.
             */
            if (e.next != null
                && e.next.request.getData() != null
                && (!con.ServProtVersKnown || con.ServerProtocolVersion < HTTP_1_1)
                && e.conn_reset) {
              addToken(req, "Connection", "close");
            }

            /* If this an HTTP/1.1 server then don't pipeline retries.
             * The problem is that if the server for some reason
             * decides not to use persistent connections and it does
             * not do a correct shutdown of the connection, then the
             * response will be ReSeT. If we did pipeline then we
             * would keep falling into this trap indefinitely.
             *
             * Note that for HTTP/1.0 servers, if they don't support
             * keep-alives then the normal code will already handle
             * this accordingly and won't pipe over the same
             * connection.
             */
            if (con.ServProtVersKnown && con.ServerProtocolVersion >= HTTP_1_1 && e.conn_reset) {
              req.dont_pipeline = true;
            }
            // The above is too risky - for moment let's be safe
            // and never pipeline retried request at all.
            req.dont_pipeline = true;

            // now resend the request

            Log.write(
                Log.MODS,
                "RtryM: Retrying request '" + req.getMethod() + " " + req.getRequestURI() + "'");

            if (e.conn_reset) req.num_retries++;
            e.response.http_resp.set(req, con.sendRequest(req, e.response.timeout));
            e.exception = null;
            e.first = null;
          }
        }
      } catch (NullPointerException npe) {
        if (got_lock) throw npe;
      } catch (ParseException pe) {
        throw new IOException(pe.getMessage());
      }

      if (re.exception != null) throw re.exception;

      re.restart = true;
      throw re;
    }
  }