protected boolean informComplete(InputStream is) {
    if (!result_informed) {

      for (int i = 0; i < listeners.size(); i++) {

        try {
          if (!((ResourceDownloaderListener) listeners.get(i)).completed(this, is)) {

            return (false);
          }
        } catch (Throwable e) {

          Debug.printStackTrace(e);

          return (false);
        }
      }

      result_informed = true;

      result_informed_data = is;
    }

    return (true);
  }
  protected void informActivity(String activity) {
    for (int i = 0; i < listeners.size(); i++) {

      try {
        ((ResourceDownloaderListener) listeners.get(i)).reportActivity(this, activity);

      } catch (Throwable e) {

        Debug.printStackTrace(e);
      }
    }
  }
  protected void informPercentDone(int percentage) {
    for (int i = 0; i < listeners.size(); i++) {

      try {
        ((ResourceDownloaderListener) listeners.get(i)).reportPercentComplete(this, percentage);

      } catch (Throwable e) {

        Debug.printStackTrace(e);
      }
    }
  }
  protected void informFailed(ResourceDownloaderException e) {
    if (!result_informed) {

      result_informed = true;

      result_informed_data = e;

      for (int i = 0; i < listeners.size(); i++) {

        try {
          ((ResourceDownloaderListener) listeners.get(i)).failed(this, e);

        } catch (Throwable f) {

          Debug.printStackTrace(f);
        }
      }
    }
  }
  protected void informAmountComplete(long amount) {
    for (int i = 0; i < listeners.size(); i++) {

      try {
        ((ResourceDownloaderListener) listeners.get(i)).reportAmountComplete(this, amount);

      } catch (NoSuchMethodError e) {

        // handle addition of this new method with old impls
      } catch (AbstractMethodError e) {

        // handle addition of this new method with old impls

      } catch (Throwable e) {

        Debug.printStackTrace(e);
      }
    }
  }
  public void addListener(ResourceDownloaderListener l) {
    listeners.add(l);

    if (result_informed) {

      if (result_informed_data instanceof InputStream) {

        l.completed(this, (InputStream) result_informed_data);
      } else {

        l.failed(this, (ResourceDownloaderException) result_informed_data);
      }
    }
  }
  public ResourceDownloaderAlternateImpl(
      ResourceDownloaderBaseImpl _parent,
      ResourceDownloader[] _delegates,
      int _max_to_try,
      boolean _random) {
    super(_parent);

    delegates = _delegates;
    max_to_try = _max_to_try;
    random = _random;

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

      ((ResourceDownloaderBaseImpl) delegates[i]).setParent(this);
    }

    if (max_to_try < 0) {

      max_to_try = delegates.length;

    } else {

      max_to_try = Math.min(max_to_try, delegates.length);
    }

    if (random) {

      List l = new ArrayList(Arrays.asList(delegates));

      delegates = new ResourceDownloader[delegates.length];

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

        delegates[i] = (ResourceDownloader) l.remove((int) (Math.random() * l.size()));
      }
    }
  }
 public void removeListener(ResourceDownloaderListener l) {
   listeners.remove(l);
 }
 protected void removeChild(ResourceDownloaderBaseImpl kid) {
   children.remove(kid);
 }
 protected void addChild(ResourceDownloaderBaseImpl kid) {
   children.add(kid);
 }