Ticket #10646: data_uri.diff

File data_uri.diff, 8.1 KB (added by sanderd17, 7 years ago)
  • src/org/openstreetmap/josm/io/remotecontrol/RequestProcessor.java

     
    3030import org.openstreetmap.josm.io.remotecontrol.handler.ImageryHandler;
    3131import org.openstreetmap.josm.io.remotecontrol.handler.ImportHandler;
    3232import org.openstreetmap.josm.io.remotecontrol.handler.LoadAndZoomHandler;
     33import org.openstreetmap.josm.io.remotecontrol.handler.LoadDataHandler;
    3334import org.openstreetmap.josm.io.remotecontrol.handler.LoadObjectHandler;
    3435import org.openstreetmap.josm.io.remotecontrol.handler.OpenFileHandler;
    3536import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler;
     
    125126    static {
    126127        addRequestHandlerClass(LoadAndZoomHandler.command, LoadAndZoomHandler.class, true);
    127128        addRequestHandlerClass(LoadAndZoomHandler.command2, LoadAndZoomHandler.class, true);
     129        addRequestHandlerClass(LoadDataHandler.command, LoadDataHandler.class, true);
    128130        addRequestHandlerClass(ImageryHandler.command, ImageryHandler.class, true);
    129131        addRequestHandlerClass(AddNodeHandler.command, AddNodeHandler.class, true);
    130132        addRequestHandlerClass(AddWayHandler.command, AddWayHandler.class, true);
  • src/org/openstreetmap/josm/io/remotecontrol/handler/LoadDataHandler.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.io.remotecontrol.handler;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
     6import java.io.ByteArrayInputStream;
     7import java.io.InputStream;
     8import java.io.UnsupportedEncodingException;
     9import java.net.URLDecoder;
     10import java.util.HashMap;
     11
     12import org.openstreetmap.josm.Main;
     13import org.openstreetmap.josm.data.osm.DataSet;
     14import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
     15import org.openstreetmap.josm.gui.PleaseWaitRunnable;
     16import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     17import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
     18import org.openstreetmap.josm.io.OsmReader;
     19
     20/**
     21 * Handler to load data directly from the URL
     22 */
     23public class LoadDataHandler extends RequestHandler {
     24
     25    /**
     26     * The remote control command name used to import data.
     27     */
     28    public static final String command = "load_data";
     29
     30    /**
     31     * Holds the data input string
     32     */
     33    private String data;
     34    /**
     35     * Holds the mime type. Currently only text/osm is supported
     36     * But it could be extended to text/csv, text/gpx, ... or even binary encoded data
     37     */
     38    private String mimeType;
     39
     40    @Override
     41    protected void handleRequest() throws RequestHandlerErrorException {
     42        try {
     43            // Transform data string to inputstream
     44            InputStream source = new ByteArrayInputStream(data.getBytes("UTF-8"));
     45            DataSet dataSet = new DataSet();
     46            if (mimeType.indexOf("text/osm") == 0)
     47                dataSet = OsmReader.parseDataSet(source, null);
     48            LoadDataTask loadDataTask = new LoadDataTask(isLoadInNewLayer(), dataSet, args.get("layer_name"));
     49            Main.worker.submit(loadDataTask);
     50        } catch (Exception e) {
     51            Main.warn("Problem with data: " + data);
     52            throw new RequestHandlerErrorException(e);
     53        }
     54    }
     55
     56    @Override
     57    public String[] getMandatoryParams() {
     58        return new String[]{"data"};
     59    }
     60
     61    @Override
     62    public String[] getOptionalParams() {
     63        return new String[] {"new_layer", "mime_type", "layer_name"};
     64    }
     65
     66    @Override
     67    public String getUsage() {
     68        return "Reads data encoded directly in the URL and adds it to the current data set";
     69    }
     70
     71    @Override
     72    public String[] getUsageExamples() {
     73        return new String[] { "/load_data?layer_name=extra_layer&new_layer=true&data=%3Cosm%3E%3Cnode%3E...%3C%2Fnode%3E%3C%2Fosm%3E" };
     74    }
     75
     76    @Override
     77    public String getPermissionMessage() {
     78        return tr("Remote Control has been asked to load the following data:")
     79                + "<br>" + data;
     80    }
     81
     82    @Override
     83    public PermissionPrefWithDefault getPermissionPref() {
     84        // Same permission as the import data, as the difference from a user pov is minimal
     85        return PermissionPrefWithDefault.IMPORT_DATA;
     86    }
     87
     88    @Override
     89    protected void parseArgs() {
     90        if (request.indexOf('?') == -1)
     91            return; // nothing to do
     92
     93        HashMap<String, String> args = new HashMap<>();
     94
     95        // The data itself shouldn't contain any &, = or ? chars.
     96        // Those are reserved for the URL parsing
     97        // and should be URL encoded as %26, %3D or %3F
     98        String query = request.substring(request.indexOf('?') + 1);
     99        String[] params = query.split("&");
     100        for (String param : params)
     101        {
     102            String[] kv = param.split("=");
     103            if (kv.length == 2)
     104                args.put(kv[0], kv[1]);
     105        }
     106        this.args = args;
     107    }
     108
     109    @Override
     110    protected void validateRequest() throws RequestHandlerBadRequestException {
     111        if (args.get("data") == null)
     112            throw new RequestHandlerBadRequestException("RemoteControl: No data defined in URL");
     113       try {
     114            data = URLDecoder.decode(args.get("data"), "UTF-8");
     115        } catch (UnsupportedEncodingException e) {
     116            throw new RequestHandlerBadRequestException("RemoteControl: UnsupportedEncodingException: " + e.getMessage(), e);
     117        }
     118        mimeType = args.get("mime_type");
     119        if (mimeType == null)
     120            mimeType = "text/osm";
     121    }
     122
     123    public class LoadDataTask extends PleaseWaitRunnable {
     124
     125        protected DataSet dataSet;
     126        protected boolean newLayer;
     127        protected String layerName;
     128
     129        public LoadDataTask(boolean newLayer, DataSet dataSet, String layerName) {
     130            super(tr("Loading data"), false);
     131            this.dataSet = dataSet;
     132            this.newLayer = newLayer;
     133            this.layerName = layerName;
     134        }
     135
     136        @Override public void realRun() {
     137            // No real run, the data is already loaded
     138        }
     139
     140        @Override protected void cancel() {
     141            // No Cancel, would be hard without a real run
     142        }
     143
     144        @Override protected void finish() {
     145            OsmDataLayer layer = getEditLayer();
     146            if (newLayer || layer == null) {
     147                layer = createNewLayer(layerName, dataSet);
     148                final boolean isDisplayingMapView = Main.isDisplayingMapView();
     149
     150                Main.main.addLayer(layer);
     151                // If the mapView is not there yet, we cannot calculate the bounds (see constructor of MapView).
     152                // Otherwise jump to the current download.
     153                if (isDisplayingMapView) {
     154                    computeBboxAndCenterScale(dataSet);
     155                }
     156            } else {
     157                layer.mergeFrom(dataSet);
     158                computeBboxAndCenterScale(dataSet);
     159                // Mark the layer as changed
     160                layer.onPostDownloadFromServer();
     161            }
     162
     163        }
     164
     165        protected OsmDataLayer getEditLayer() {
     166            if (!Main.isDisplayingMapView()) return null;
     167            return Main.main.getEditLayer();
     168        }
     169
     170        protected void computeBboxAndCenterScale(DataSet data) {
     171            BoundingXYVisitor v = new BoundingXYVisitor();
     172            v.computeBoundingBox(data.getNodes());
     173            Main.map.mapView.recalculateCenterScale(v);
     174        }
     175
     176        protected OsmDataLayer createNewLayer(String layerName, DataSet data) {
     177            if (layerName == null || layerName.isEmpty()) {
     178                layerName = OsmDataLayer.createNewName();
     179            }
     180            return new OsmDataLayer(data, layerName, null);
     181        }
     182    }
     183}