    001// License: GPL. For details, see LICENSE file.
    002package org.openstreetmap.josm.plugins.streetside.io.download;
    003
    004import java.awt.GraphicsEnvironment;
    005import java.io.IOException;
    006import java.net.HttpURLConnection;
    007import java.net.URL;
    008import java.net.URLConnection;
    009import java.util.function.Function;
    010
    011import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;
    012
    013import org.openstreetmap.josm.data.Bounds;
    014import org.openstreetmap.josm.gui.Notification;
    015import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
    016import org.openstreetmap.josm.tools.I18n;
    017import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
    018import org.openstreetmap.josm.tools.Logging;
    019
    020public abstract class BoundsDownloadRunnable implements Runnable {
    021
    022  protected Bounds bounds;
    023  protected abstract Function<Bounds, URL> getUrlGenerator();
    024
    025  public BoundsDownloadRunnable(final Bounds bounds) {
    026    this.bounds = bounds;
    027  }
    028
    029  @Override
    030  public void run() {
    031    URL nextURL = getUrlGenerator().apply(bounds);
    032    try {
    033      while (nextURL != null) {
    034        if (Thread.interrupted()) {
    035          Logging.debug("{} for {} interrupted!", getClass().getSimpleName(), bounds.toString());
    036          return;
    037        }
    038        final URLConnection con = nextURL.openConnection();
    039        run(con);
    040        nextURL = APIv3.parseNextFromLinkHeaderValue(con.getHeaderField("Link"));
    041      }
    042    } catch (IOException e) {
    043      String message = I18n.tr("Could not read from URL {0}!", nextURL.toString());
    044      Logging.log(Logging.LEVEL_WARN, message, e);
    045      if (!GraphicsEnvironment.isHeadless()) {
    046        new Notification(message)
    047          .setIcon(StreetsidePlugin.LOGO.setSize(ImageSizes.LARGEICON).get())
    048          .setDuration(Notification.TIME_LONG)
    049          .show();
    050      }
    051      e.printStackTrace();
    052    }
    053  }
    054
    055  /**
    056   * Logs information about the given connection via {@link Logging#info(String)}.
    057   * If it's a {@link HttpURLConnection}, the request method, the response code and the URL itself are logged.
    058   * Otherwise only the URL is logged.
    059   * @param con the {@link URLConnection} for which information is logged
    060   * @param info an additional info text, which is appended to the output in braces
    061   * @throws IOException if {@link HttpURLConnection#getResponseCode()} throws an {@link IOException}
    062   */
    063  public static void logConnectionInfo(final URLConnection con, final String info) throws IOException {
    064    final StringBuilder message;
    065    if (con instanceof HttpURLConnection) {
    066      message = new StringBuilder(((HttpURLConnection) con).getRequestMethod())
    067        .append(' ').append(con.getURL())
    068        .append(" → ").append(((HttpURLConnection) con).getResponseCode());
    069    } else {
    070      message = new StringBuilder("Download from ").append(con.getURL());
    071    }
    072    if (info != null && info.length() >= 1) {
    073      message.append(" (").append(info).append(')');
    074    }
    075    Logging.info(message.toString());
    076  }
    077
    078  public abstract void run(final URLConnection connection) throws IOException;
    079}