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}