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}