    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    Logging.debug("nextURL: {0}", nextURL.toString());
    033    try {
    034      while (nextURL != null) {
    035        if (Thread.interrupted()) {
    036          Logging.debug("{} for {} interrupted!", getClass().getSimpleName(), bounds.toString());
    037          return;
    038        }
    039        final URLConnection con = nextURL.openConnection();
    040        run(con);
    041        nextURL = APIv3.parseNextFromLinkHeaderValue(con.getHeaderField("Link"));
    042      }
    043    } catch (IOException e) {
    044      String message = I18n.tr("Could not read from URL {0}!", nextURL.toString());
    045      Logging.log(Logging.LEVEL_WARN, message, e);
    046      if (!GraphicsEnvironment.isHeadless()) {
    047        new Notification(message)
    048          .setIcon(StreetsidePlugin.LOGO.setSize(ImageSizes.LARGEICON).get())
    049          .setDuration(Notification.TIME_LONG)
    050          .show();
    051      }
    052      e.printStackTrace();
    053    }
    054  }
    055
    056  /**
    057   * Logs information about the given connection via {@link Logging#info(String)}.
    058   * If it's a {@link HttpURLConnection}, the request method, the response code and the URL itself are logged.
    059   * Otherwise only the URL is logged.
    060   * @param con the {@link URLConnection} for which information is logged
    061   * @param info an additional info text, which is appended to the output in braces
    062   * @throws IOException if {@link HttpURLConnection#getResponseCode()} throws an {@link IOException}
    063   */
    064  public static void logConnectionInfo(final URLConnection con, final String info) throws IOException {
    065    final StringBuilder message;
    066    if (con instanceof HttpURLConnection) {
    067      message = new StringBuilder(((HttpURLConnection) con).getRequestMethod())
    068        .append(' ').append(con.getURL())
    069        .append(" → ").append(((HttpURLConnection) con).getResponseCode());
    070    } else {
    071      message = new StringBuilder("Download from ").append(con.getURL());
    072    }
    073    if (info != null && info.length() >= 1) {
    074      message.append(" (").append(info).append(')');
    075    }
    076    Logging.debug(message.toString());
    077  }
    078
    079  public abstract void run(final URLConnection connection) throws IOException;
    080}