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