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