001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io.remotecontrol.handler;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.net.MalformedURLException;
007import java.net.URL;
008import java.util.Collection;
009import java.util.LinkedHashSet;
010import java.util.Set;
011
012import org.openstreetmap.josm.Main;
013import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
014import org.openstreetmap.josm.actions.downloadtasks.DownloadTask;
015import org.openstreetmap.josm.gui.MainApplication;
016import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
017import org.openstreetmap.josm.spi.preferences.Config;
018import org.openstreetmap.josm.tools.Logging;
019import org.openstreetmap.josm.tools.Utils;
020
021/**
022 * Handler for import request
023 */
024public class ImportHandler extends RequestHandler.RawURLParseRequestHandler {
025
026    /**
027     * The remote control command name used to import data.
028     */
029    public static final String command = "import";
030
031    private URL url;
032    private Collection<DownloadTask> suitableDownloadTasks;
033
034    @Override
035    protected void handleRequest() throws RequestHandlerErrorException {
036        try {
037            if (suitableDownloadTasks.isEmpty()) {
038                // It should maybe be better to reject the request in that case ?
039                // For compatibility reasons with older instances of JOSM, arbitrary choice of DownloadOsmTask
040                // As of 2015-04, Overpass Turbo requires this branch of code ...
041                Logging.debug("Remote control, /import: defaulting to DownloadOsmTask");
042                new DownloadOsmTask().loadUrl(getDownloadParams(), url.toExternalForm(), null);
043            } else if (Config.getPref().getBoolean("remotecontrol.import.interactive", true)) {
044                // OpenLocationAction queries the user if more than one task is suitable
045                MainApplication.getMenu().openLocation.openUrl(getDownloadParams(), url.toExternalForm());
046            } else {
047                // Otherwise perform all tasks
048                for (DownloadTask task : suitableDownloadTasks) {
049                    task.loadUrl(getDownloadParams(), url.toExternalForm(), null);
050                }
051            }
052        } catch (RuntimeException ex) { // NOPMD
053            Logging.warn("RemoteControl: Error parsing import remote control request:");
054            Logging.error(ex);
055            throw new RequestHandlerErrorException(ex);
056        }
057    }
058
059    @Override
060    public String[] getMandatoryParams() {
061        return new String[]{"url"};
062    }
063
064    @Override
065    public String[] getOptionalParams() {
066        return new String[] {"new_layer", "layer_name", "layer_locked", "download_policy", "upload_policy"};
067    }
068
069    @Override
070    public String getUsage() {
071        return "downloads the specified OSM file and adds it to the current data set";
072    }
073
074    @Override
075    public String[] getUsageExamples() {
076        return new String[] {"/import?url=" + Utils.encodeUrl(
077                Main.getJOSMWebsite()+"/browser/josm/trunk/data_nodist/direction-arrows.osm?format=txt")};
078    }
079
080    @Override
081    public String getPermissionMessage() {
082        // URL can be any suitable URL giving back OSM data, including OSM API calls, even if calls to the main API
083        // should rather be passed to LoadAndZoomHandler or LoadObjectHandler.
084        // Other API instances will however use the import handler to force JOSM to make requests to this API instance.
085        // (Example with OSM-FR website that makes calls to the OSM-FR API)
086        // For user-friendliness, let's try to decode these OSM API calls to give a better confirmation message.
087        Set<String> taskMessages = new LinkedHashSet<>();
088        if (suitableDownloadTasks != null && !suitableDownloadTasks.isEmpty()) {
089            for (DownloadTask task : suitableDownloadTasks) {
090                taskMessages.add(Utils.firstNonNull(task.getConfirmationMessage(url), url.toString()));
091            }
092        }
093        return tr("Remote Control has been asked to import data from the following URL:")
094                + Utils.joinAsHtmlUnorderedList(taskMessages);
095    }
096
097    @Override
098    public PermissionPrefWithDefault getPermissionPref() {
099        return PermissionPrefWithDefault.IMPORT_DATA;
100    }
101
102    @Override
103    protected void validateRequest() throws RequestHandlerBadRequestException {
104        validateDownloadParams();
105        String urlString = args != null ? args.get("url") : null;
106        if (Config.getPref().getBoolean("remotecontrol.importhandler.fix_url_query", true)) {
107            urlString = Utils.fixURLQuery(urlString);
108        }
109        try {
110            // Ensure the URL is valid
111            url = new URL(urlString);
112        } catch (MalformedURLException e) {
113            throw new RequestHandlerBadRequestException("MalformedURLException: "+e.getMessage(), e);
114        }
115        // Find download tasks for the given URL
116        suitableDownloadTasks = MainApplication.getMenu().openLocation.findDownloadTasks(urlString, true);
117    }
118}