docs: @Override
      public SyndFeed retrieveFeed(final String userAgent, final URL feedUrl) throws IllegalArgumentException, IOException, FeedException, FetcherException {
          if (feedUrl == null) {
              throw new IllegalArgumentException("null is not a valid URL");
          }
  
          final URLConnection connection = feedUrl.openConnection();
          if (!(connection instanceof HttpURLConnection)) {
              throw new IllegalArgumentException(feedUrl.toExternalForm() + " is not a valid HTTP Url");
          }
          final HttpURLConnection httpConnection = (HttpURLConnection) connection;
          if (connectTimeout >= 0) {
              httpConnection.setConnectTimeout(connectTimeout);
          }
          // httpConnection.setInstanceFollowRedirects(true); // this is true by default, but can be
          // changed on a claswide basis
  
          final FeedFetcherCache cache = getFeedInfoCache();
          if (cache != null) {
              SyndFeedInfo syndFeedInfo = cache.getFeedInfo(feedUrl);
              setRequestHeaders(connection, syndFeedInfo, userAgent);
              httpConnection.connect();
              try {
                  fireEvent(FetcherEvent.EVENT_TYPE_FEED_POLLED, connection);
  
                  if (syndFeedInfo == null) {
                      // this is a feed that hasn't been retrieved
                      syndFeedInfo = new SyndFeedInfo();
                      retrieveAndCacheFeed(feedUrl, syndFeedInfo, httpConnection);
                  } else {
                      // check the response code
                      final int responseCode = httpConnection.getResponseCode();
                      if (responseCode != HttpURLConnection.HTTP_NOT_MODIFIED) {
                          // the response code is not 304 NOT MODIFIED
                          // This is either because the feed server
                          // does not support condition gets
                          // or because the feed hasn't changed
                          retrieveAndCacheFeed(feedUrl, syndFeedInfo, httpConnection);
                      } else {
                          // the feed does not need retrieving
                          fireEvent(FetcherEvent.EVENT_TYPE_FEED_UNCHANGED, connection);
                      }
                  }
  
                  return syndFeedInfo.getSyndFeed();
              } finally {
                  httpConnection.disconnect();
              }
          } else {
              fireEvent(FetcherEvent.EVENT_TYPE_FEED_POLLED, connection);
              InputStream inputStream = null;
              setRequestHeaders(connection, null, userAgent);
  
              httpConnection.connect();
              try {
                  inputStream = httpConnection.getInputStream();
                  return getSyndFeedFromStream(inputStream, connection);
              } catch (final java.io.IOException e) {
                  handleErrorCodes(((HttpURLConnection) connection).getResponseCode());
              } finally {
                  IO.close(inputStream);
                  httpConnection.disconnect();
              }
              // we will never actually get to this line
              return null;
          }
      }