// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.io.remotecontrol.handler;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.io.IllegalDataException;
import org.openstreetmap.josm.io.OsmReader;
import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
import org.openstreetmap.josm.tools.Utils;
/**
* Handler to load data directly from the URL.
* @since 7636
*/
public class LoadDataHandler extends RequestHandler {
private static final String OSM_MIME_TYPE = "application/x-osm+xml";
/**
* The remote control command name used to import data.
*/
public static final String command = "load_data";
/**
* Holds the data input string
*/
private String data;
/**
* Holds the parsed data set
*/
private DataSet dataSet;
@Override
protected void handleRequest() throws RequestHandlerErrorException {
Main.worker.submit(new LoadDataTask(isLoadInNewLayer(), dataSet, args.get("layer_name")));
}
@Override
public String[] getMandatoryParams() {
return new String[]{"data"};
}
@Override
public String[] getOptionalParams() {
return new String[] {"new_layer", "mime_type", "layer_name"};
}
@Override
public String getUsage() {
return "Reads data encoded directly in the URL and adds it to the current data set";
}
@Override
public String[] getUsageExamples() {
return new String[]{
"/load_data?layer_name=extra_layer&new_layer=true&data=" +
Utils.encodeUrl("<osm version='0.6'><node id='-1' lat='1' lon='2' /></osm>")};
}
@Override
public String getPermissionMessage() {
return tr("Remote Control has been asked to load the following data:")
+ "<br>" + data;
}
@Override
public PermissionPrefWithDefault getPermissionPref() {
// Same permission as the import data, as the difference from a user pov is minimal
return PermissionPrefWithDefault.IMPORT_DATA;
}
@Override
protected void validateRequest() throws RequestHandlerBadRequestException {
this.data = args.get("data");
/**
* Holds the mime type. Currently only OSM_MIME_TYPE is supported
* But it could be extended to text/csv, application/gpx+xml, ... or even binary encoded data
*/
final String mimeType = Utils.firstNonNull(args.get("mime_type"), OSM_MIME_TYPE);
try {
if (OSM_MIME_TYPE.equals(mimeType)) {
final ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
dataSet = OsmReader.parseDataSet(in, null);
} else {
dataSet = new DataSet();
}
} catch (IllegalDataException e) {
throw new RequestHandlerBadRequestException("Failed to parse " + data + ": " + e.getMessage(), e);
}
}
protected static class LoadDataTask extends DownloadOsmTask.AbstractInternalTask {
protected final String layerName;
/**
* Constructs a new {@code LoadDataTask}.
* @param newLayer if {@code true}, force download to a new layer
* @param dataSet data set
* @param layerName layer name
*/
public LoadDataTask(boolean newLayer, DataSet dataSet, String layerName) {
super(newLayer, tr("Loading data"), false, true);
this.dataSet = dataSet;
this.layerName = layerName;
}
@Override
public void realRun() {
// No real run, the data is already loaded
}
@Override
protected void cancel() {
// No Cancel, would be hard without a real run
}
@Override
protected void finish() {
loadData(layerName, null);
}
}
}