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.io.ByteArrayInputStream; 007import java.nio.charset.StandardCharsets; 008 009import org.openstreetmap.josm.Main; 010import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask; 011import org.openstreetmap.josm.data.osm.DataSet; 012import org.openstreetmap.josm.io.IllegalDataException; 013import org.openstreetmap.josm.io.OsmReader; 014import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault; 015import org.openstreetmap.josm.tools.Utils; 016 017/** 018 * Handler to load data directly from the URL. 019 * @since 7636 020 */ 021public class LoadDataHandler extends RequestHandler { 022 023 private static final String OSM_MIME_TYPE = "application/x-osm+xml"; 024 025 /** 026 * The remote control command name used to import data. 027 */ 028 public static final String command = "load_data"; 029 030 /** 031 * Holds the data input string 032 */ 033 private String data; 034 035 /** 036 * Holds the parsed data set 037 */ 038 private DataSet dataSet; 039 040 @Override 041 protected void handleRequest() throws RequestHandlerErrorException { 042 Main.worker.submit(new LoadDataTask(isLoadInNewLayer(), dataSet, args.get("layer_name"))); 043 } 044 045 @Override 046 public String[] getMandatoryParams() { 047 return new String[]{"data"}; 048 } 049 050 @Override 051 public String[] getOptionalParams() { 052 return new String[] {"new_layer", "mime_type", "layer_name"}; 053 } 054 055 @Override 056 public String getUsage() { 057 return "Reads data encoded directly in the URL and adds it to the current data set"; 058 } 059 060 @Override 061 public String[] getUsageExamples() { 062 return new String[]{ 063 "/load_data?layer_name=extra_layer&new_layer=true&data=" + 064 Utils.encodeUrl("<osm version='0.6'><node id='-1' lat='1' lon='2' /></osm>")}; 065 } 066 067 @Override 068 public String getPermissionMessage() { 069 return tr("Remote Control has been asked to load the following data:") 070 + "<br>" + data; 071 } 072 073 @Override 074 public PermissionPrefWithDefault getPermissionPref() { 075 // Same permission as the import data, as the difference from a user pov is minimal 076 return PermissionPrefWithDefault.IMPORT_DATA; 077 } 078 079 @Override 080 protected void validateRequest() throws RequestHandlerBadRequestException { 081 this.data = args.get("data"); 082 /** 083 * Holds the mime type. Currently only OSM_MIME_TYPE is supported 084 * But it could be extended to text/csv, application/gpx+xml, ... or even binary encoded data 085 */ 086 final String mimeType = Utils.firstNonNull(args.get("mime_type"), OSM_MIME_TYPE); 087 try { 088 if (OSM_MIME_TYPE.equals(mimeType)) { 089 final ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)); 090 dataSet = OsmReader.parseDataSet(in, null); 091 } else { 092 dataSet = new DataSet(); 093 } 094 } catch (IllegalDataException e) { 095 throw new RequestHandlerBadRequestException("Failed to parse " + data + ": " + e.getMessage(), e); 096 } 097 } 098 099 protected static class LoadDataTask extends DownloadOsmTask.AbstractInternalTask { 100 101 protected final String layerName; 102 103 /** 104 * Constructs a new {@code LoadDataTask}. 105 * @param newLayer if {@code true}, force download to a new layer 106 * @param dataSet data set 107 * @param layerName layer name 108 */ 109 public LoadDataTask(boolean newLayer, DataSet dataSet, String layerName) { 110 super(newLayer, tr("Loading data"), false, true); 111 this.dataSet = dataSet; 112 this.layerName = layerName; 113 } 114 115 @Override 116 public void realRun() { 117 // No real run, the data is already loaded 118 } 119 120 @Override 121 protected void cancel() { 122 // No Cancel, would be hard without a real run 123 } 124 125 @Override 126 protected void finish() { 127 loadData(layerName, null); 128 } 129 } 130}