Changeset 18780 in josm


Ignore:
Timestamp:
2023-07-26T17:37:57+02:00 (16 months ago)
Author:
taylor.smock
Message:

Fix #22733: Add UI feedback for url guessing, account for nan responses from servers

Location:
trunk/src/org/openstreetmap/josm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/preferences/imagery/AddWMSLayerPanel.java

    r17657 r18780  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.awt.GraphicsEnvironment;
     7import java.awt.event.ActionEvent;
    68import java.awt.event.ActionListener;
    79import java.io.IOException;
     
    1618import javax.swing.JCheckBox;
    1719import javax.swing.JComboBox;
     20import javax.swing.JComponent;
    1821import javax.swing.JLabel;
    1922import javax.swing.JOptionPane;
     
    2427import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
    2528import org.openstreetmap.josm.data.imagery.LayerDetails;
     29import org.openstreetmap.josm.gui.MainApplication;
     30import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    2631import org.openstreetmap.josm.gui.bbox.SlippyMapBBoxChooser;
     32import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
     33import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     34import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor;
    2735import org.openstreetmap.josm.gui.util.GuiHelper;
    2836import org.openstreetmap.josm.gui.widgets.JosmTextArea;
     
    8290        add(name, GBC.eop().fill(GBC.HORIZONTAL));
    8391
    84         getLayers.addActionListener(e -> {
    85             try {
    86                 wms = new WMSImagery(Utils.strip(rawUrl.getText()), getCommonHeaders());
    87                 tree.updateTree(wms);
    88                 Collection<String> wmsFormats = wms.getFormats();
    89                 formats.setModel(new DefaultComboBoxModel<>(wmsFormats.toArray(new String[0])));
    90                 formats.setSelectedItem(wms.getPreferredFormat());
    91             } catch (MalformedURLException | InvalidPathException ex1) {
    92                 Logging.log(Logging.LEVEL_ERROR, ex1);
    93                 JOptionPane.showMessageDialog(getParent(), tr("Invalid service URL."),
    94                         tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
    95             } catch (IOException ex2) {
    96                 Logging.log(Logging.LEVEL_ERROR, ex2);
    97                 JOptionPane.showMessageDialog(getParent(), tr("Could not retrieve WMS layer list."),
    98                         tr("WMS Error"), JOptionPane.ERROR_MESSAGE);
    99             } catch (WMSImagery.WMSGetCapabilitiesException ex3) {
    100                 String incomingData = ex3.getIncomingData() != null ? ex3.getIncomingData().trim() : "";
    101                 String title = tr("WMS Error");
    102                 StringBuilder message = new StringBuilder(tr("Could not parse WMS layer list."));
    103                 Logging.log(Logging.LEVEL_ERROR, "Could not parse WMS layer list. Incoming data:\n"+incomingData, ex3);
    104                 if ((incomingData.startsWith("<html>") || incomingData.startsWith("<HTML>"))
    105                   && (incomingData.endsWith("</html>") || incomingData.endsWith("</HTML>"))) {
    106                     GuiHelper.notifyUserHtmlError(this, title, message.toString(), incomingData);
    107                 } else {
    108                     if (ex3.getMessage() != null) {
    109                         message.append('\n').append(ex3.getMessage());
    110                     }
    111                     JOptionPane.showMessageDialog(getParent(), message.toString(), title, JOptionPane.ERROR_MESSAGE);
    112                 }
    113             }
    114         });
     92        getLayers.addActionListener(e -> MainApplication.worker.execute(new GetCapabilitiesRunnable(e)));
    11593
    11694        ActionListener availabilityManagerAction = a -> {
     
    226204        }
    227205    }
     206
     207    /**
     208     * Perform the get WMS layers network calls in a separate thread, mostly to allow for cancellation
     209     */
     210    private class GetCapabilitiesRunnable extends PleaseWaitRunnable {
     211        private final ActionEvent actionEvent;
     212
     213        GetCapabilitiesRunnable(ActionEvent actionEvent) {
     214            super(tr("Trying WMS urls"), GraphicsEnvironment.isHeadless() ? NullProgressMonitor.INSTANCE : new PleaseWaitProgressMonitor(),
     215                    false);
     216            this.actionEvent = actionEvent;
     217        }
     218
     219        @Override
     220        protected void cancel() {
     221            // We don't really have something we can do -- we use the monitor to pass the cancel state on
     222        }
     223
     224        @Override
     225        protected void realRun() {
     226            if (actionEvent.getSource() instanceof JComponent) {
     227                GuiHelper.runInEDT(() -> ((JComponent) actionEvent.getSource()).setEnabled(false));
     228            }
     229            ProgressMonitor monitor = getProgressMonitor();
     230            try {
     231                wms = new WMSImagery(Utils.strip(rawUrl.getText()), getCommonHeaders(), monitor);
     232            } catch (MalformedURLException | InvalidPathException ex1) {
     233                Logging.log(Logging.LEVEL_ERROR, ex1);
     234                GuiHelper.runInEDT(() -> JOptionPane.showMessageDialog(getParent(), tr("Invalid service URL."),
     235                        tr("WMS Error"), JOptionPane.ERROR_MESSAGE));
     236            } catch (IOException ex2) {
     237                Logging.log(Logging.LEVEL_ERROR, ex2);
     238                GuiHelper.runInEDT(() -> JOptionPane.showMessageDialog(getParent(), tr("Could not retrieve WMS layer list."),
     239                        tr("WMS Error"), JOptionPane.ERROR_MESSAGE));
     240            } catch (WMSImagery.WMSGetCapabilitiesException ex3) {
     241                String incomingData = ex3.getIncomingData() != null ? ex3.getIncomingData().trim() : "";
     242                String title = tr("WMS Error");
     243                StringBuilder message = new StringBuilder(tr("Could not parse WMS layer list."));
     244                Logging.log(Logging.LEVEL_ERROR, "Could not parse WMS layer list. Incoming data:\n"+incomingData, ex3);
     245                if ((incomingData.startsWith("<html>") || incomingData.startsWith("<HTML>"))
     246                        && (incomingData.endsWith("</html>") || incomingData.endsWith("</HTML>"))) {
     247                    GuiHelper.runInEDT(() -> GuiHelper.notifyUserHtmlError(AddWMSLayerPanel.this, title, message.toString(), incomingData));
     248                } else {
     249                    if (ex3.getMessage() != null) {
     250                        message.append('\n').append(ex3.getMessage());
     251                    }
     252                    GuiHelper.runInEDT(() -> JOptionPane.showMessageDialog(getParent(), message.toString(), title, JOptionPane.ERROR_MESSAGE));
     253                }
     254            }
     255        }
     256
     257        @Override
     258        protected void finish() {
     259            if (wms != null) {
     260                GuiHelper.runInEDT(() -> {
     261                    tree.updateTree(wms);
     262                    Collection<String> wmsFormats = wms.getFormats();
     263                    formats.setModel(new DefaultComboBoxModel<>(wmsFormats.toArray(new String[0])));
     264                    formats.setSelectedItem(wms.getPreferredFormat());
     265                });
     266            }
     267            if (actionEvent.getSource() instanceof JComponent) {
     268                GuiHelper.runInEDT(() -> ((JComponent) actionEvent.getSource()).setEnabled(true));
     269            }
     270        }
     271    }
    228272}
  • trunk/src/org/openstreetmap/josm/io/imagery/WMSImagery.java

    r18211 r18780  
    1212import java.nio.file.InvalidPathException;
    1313import java.util.ArrayList;
     14import java.util.Arrays;
    1415import java.util.Collection;
    1516import java.util.Collections;
     
    3637import org.openstreetmap.josm.data.projection.Projection;
    3738import org.openstreetmap.josm.data.projection.Projections;
     39import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
     40import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    3841import org.openstreetmap.josm.io.CachedFile;
    3942import org.openstreetmap.josm.tools.Logging;
     
    151154     */
    152155    public WMSImagery(String url, Map<String, String> headers) throws IOException, WMSGetCapabilitiesException {
     156        this(url, headers, NullProgressMonitor.INSTANCE);
     157    }
     158
     159    /**
     160     * Make getCapabilities request towards given URL using headers
     161     * @param url service url
     162     * @param headers HTTP headers to be sent with request
     163     * @param monitor Feedback for which URL we are currently trying, the integer is the <i>total number of urls</i> we are going to try
     164     * @throws IOException when connection error when fetching get capabilities document
     165     * @throws WMSGetCapabilitiesException when there are errors when parsing get capabilities document
     166     * @throws InvalidPathException if a Path object cannot be constructed for the capabilities cached file
     167     * @since xxx
     168     */
     169    public WMSImagery(String url, Map<String, String> headers, ProgressMonitor monitor)
     170            throws IOException, WMSGetCapabilitiesException {
    153171        if (headers != null) {
    154172            this.headers.putAll(headers);
     
    157175        IOException savedExc = null;
    158176        String workingAddress = null;
     177        final String[] baseAdditions = {
     178            normalizeUrl(url),
     179            url,
     180            url + CAPABILITIES_QUERY_STRING,
     181        };
     182        final String[] versionAdditions = {"", "&VERSION=1.3.0", "&VERSION=1.1.1"};
     183        final int totalNumberOfUrlsToTry = baseAdditions.length * versionAdditions.length;
     184        monitor.setTicksCount(totalNumberOfUrlsToTry);
    159185        url_search:
    160         for (String z: new String[]{
    161                 normalizeUrl(url),
    162                 url,
    163                 url + CAPABILITIES_QUERY_STRING,
    164         }) {
    165             for (String ver: new String[]{"", "&VERSION=1.3.0", "&VERSION=1.1.1"}) {
     186        for (String z : baseAdditions) {
     187            for (String ver : versionAdditions) {
     188                if (monitor.isCanceled()) {
     189                    break url_search;
     190                }
    166191                try {
     192                    monitor.setCustomText(z + ver);
     193                    monitor.worked(1);
    167194                    attemptGetCapabilities(z + ver);
    168195                    workingAddress = z;
     
    193220            }
    194221        }
    195 
    196222        if (savedExc != null) {
    197223            throw savedExc;
     
    616642
    617643    private static Bounds parseBBox(Projection conv, String miny, String minx, String maxy, String maxx) {
    618         if (miny == null || minx == null || maxy == null || maxx == null) {
     644        if (miny == null || minx == null || maxy == null || maxx == null || Arrays.asList(miny, minx, maxy, maxx).contains("nan")) {
    619645            return null;
    620646        }
Note: See TracChangeset for help on using the changeset viewer.