Ticket #8228: rc.patch

File rc.patch, 20.5 KB (added by simon04, 13 years ago)
  • src/org/openstreetmap/josm/io/remotecontrol/RemoteControl.java

    diff --git a/src/org/openstreetmap/josm/io/remotecontrol/RemoteControl.java b/src/org/openstreetmap/josm/io/remotecontrol/RemoteControl.java
    index 248303e..1a89d9c 100644
    a b  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.io.remotecontrol;
    33
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
     6import com.sun.net.httpserver.HttpExchange;
     7import com.sun.net.httpserver.HttpHandler;
     8import com.sun.net.httpserver.HttpServer;
     9import java.io.IOException;
     10import java.io.OutputStreamWriter;
     11import java.net.BindException;
     12import java.net.InetAddress;
     13import java.net.InetSocketAddress;
     14import java.util.Arrays;
     15import java.util.HashMap;
     16import java.util.Map;
    417import org.openstreetmap.josm.data.preferences.BooleanProperty;
     18import org.openstreetmap.josm.io.remotecontrol.handler.AddNodeHandler;
     19import org.openstreetmap.josm.io.remotecontrol.handler.AddWayHandler;
     20import org.openstreetmap.josm.io.remotecontrol.handler.ImageryHandler;
     21import org.openstreetmap.josm.io.remotecontrol.handler.ImportHandler;
     22import org.openstreetmap.josm.io.remotecontrol.handler.LoadAndZoomHandler;
     23import org.openstreetmap.josm.io.remotecontrol.handler.LoadObjectHandler;
     24import org.openstreetmap.josm.io.remotecontrol.handler.OpenFileHandler;
    525import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler;
     26import org.openstreetmap.josm.io.remotecontrol.handler.VersionHandler;
     27import org.openstreetmap.josm.tools.Utils;
    628
    729/**
    830 * Manager class for remote control operations.
    import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler;  
    1032 * IMPORTANT! increment the minor version on compatible API extensions
    1133 * and increment the major version and set minor to 0 on incompatible changes.
    1234 */
    13 public class RemoteControl
    14 {
     35public class RemoteControl {
    1536    /**
    1637     * If the remote cotrol feature is enabled or disabled. If disabled,
    1738     * it should not start the server.
    public class RemoteControl  
    1940    public static final BooleanProperty PROP_REMOTECONTROL_ENABLED = new BooleanProperty("remotecontrol.enabled", false);
    2041
    2142    /**
     43     * Default port for the HTTP server
     44     */
     45    public static final int DEFAULT_PORT = 8111;
     46
     47    /**
    2248     * RemoteControl HTTP protocol version. Change minor number for compatible
    2349     * interface extensions. Change major number in case of incompatible
    2450     * changes.
    public class RemoteControl  
    2753    static final int protocolMinorVersion = 4;
    2854
    2955    /**
     56     * RemoteControl protocol version. Change minor number for compatible
     57     * interface extensions. Change major number in case of incompatible
     58     * changes.
     59     */
     60    public static final String PROTOCOLVERSION = "{\"protocolversion\": {\"major\": " +
     61            RemoteControl.protocolMajorVersion + ", \"minor\": " +
     62            RemoteControl.protocolMinorVersion +
     63            "}, \"application\": \"JOSM RemoteControl\"}";
     64
     65    private static final Map<String, Class<? extends RequestHandler>> handlers = new HashMap<String, java.lang.Class<? extends RequestHandler>>();
     66
     67    public static HttpServer SERVER;
     68
     69    static {
     70        try {
     71            SERVER = HttpServer.create(new InetSocketAddress(InetAddress.getLocalHost(), DEFAULT_PORT), 0);
     72            SERVER.createContext("/", new UsageHandler());
     73            addRequestHandlerClass(LoadAndZoomHandler.command, LoadAndZoomHandler.class, true);
     74            addRequestHandlerClass(LoadAndZoomHandler.command2, LoadAndZoomHandler.class, true);
     75            addRequestHandlerClass(ImageryHandler.command, ImageryHandler.class, true);
     76            addRequestHandlerClass(AddNodeHandler.command, AddNodeHandler.class, true);
     77            addRequestHandlerClass(AddWayHandler.command, AddWayHandler.class, true);
     78            addRequestHandlerClass(ImportHandler.command, ImportHandler.class, true);
     79            addRequestHandlerClass(VersionHandler.command, VersionHandler.class, true);
     80            addRequestHandlerClass(LoadObjectHandler.command, LoadObjectHandler.class, true);
     81            addRequestHandlerClass(OpenFileHandler.command, OpenFileHandler.class, true);
     82        } catch (BindException ex) {
     83            System.err.println(tr("Warning: Cannot start remotecontrol server on port {0}: {1}",
     84                    Integer.toString(DEFAULT_PORT), ex.getLocalizedMessage()));
     85        } catch (IOException ioe) {
     86            ioe.printStackTrace();
     87        }
     88    }
     89
     90    /**
    3091     * Starts the remote control server
    3192     */
    3293    public static void start() {
    33         RemoteControlHttpServer.restartRemoteControlHttpServer();
     94        SERVER.start();
     95        System.out.println("RemoteControl: Accepting connections on port " + DEFAULT_PORT);
     96
    3497    }
    3598
    3699    /**
    37      * Adds external request handler.
    38      * Can be used by plugins that want to use remote control.
    39      *
    40      * @param command The command name.
     100     * Add external request handler. Message can be suppressed (for internal use)
     101     *
     102     * @param command      The command to handle.
    41103     * @param handlerClass The additional request handler.
     104     * @param silent       Don't show message if true.
    42105     */
    43     public void addRequestHandler(String command, Class<? extends RequestHandler> handlerClass)
    44     {
    45         RequestProcessor.addRequestHandlerClass(command, handlerClass);
     106    public static void addRequestHandlerClass(String command, final Class<? extends RequestHandler> handlerClass, boolean silent) {
     107        final String commandSlash = command.startsWith("/") ? command : ("/" + command);
     108        handlers.put(commandSlash, handlerClass);
     109        SERVER.createContext(commandSlash, new HttpHandler() {
     110            @Override
     111            public void handle(HttpExchange exchange) throws IOException {
     112                try {
     113                    System.out.println("RemoteControl received: " + exchange.getRequestURI());
     114                    RequestHandler h = handlerClass.newInstance();
     115                    h.setCommand(commandSlash);
     116                    h.setUrl(exchange.getRequestURI().toString());
     117                    h.handle();
     118                    sendResponse(exchange, 200, h.getContentType(), h.getContent());
     119                } catch (Exception e) {
     120                    throw new RuntimeException(e);
     121                }
     122            }
     123        });
     124        if (!silent) {
     125            System.out.println("RemoteControl: adding command \"" + command + "\" (handled by " + handlerClass.getSimpleName() + ")");
     126        }
     127    }
     128
     129    private static class UsageHandler implements HttpHandler {
     130        @Override
     131        public void handle(HttpExchange exchange) throws IOException {
     132            try {
     133                StringBuilder usage = new StringBuilder(1024);
     134                for (Map.Entry<String, Class<? extends RequestHandler>> handler : handlers.entrySet()) {
     135                    final RequestHandler handlerInstance = handler.getValue().newInstance();
     136                    final String[] mandatory = handlerInstance.getMandatoryParams();
     137                    usage.append("<li>");
     138                    usage.append(handler.getKey());
     139                    usage.append(": ");
     140                    usage.append(handlerInstance.getUsage());
     141                    if (mandatory != null) {
     142                        usage.append("<br/>mandatory parameter: ").append(Utils.join(", ", Arrays.asList(mandatory)));
     143                        usage.append("<br/>usage examples:").append(Utils.joinAsHtmlUnorderedList(handlerInstance.getUsageExamples()));
     144                    }
     145                    usage.append("</li>");
     146                }
     147                String help = "<h1>JOSM RemoteControl</h1>"
     148                        + "No command specified! The following commands are available:<ul>"
     149                        + usage.toString()
     150                        + "</ul>";
     151                sendResponse(exchange, 400, "text/html", help);
     152            } catch (Exception e) {
     153                throw new RuntimeException(e);
     154            }
     155        }
     156    }
     157
     158    private static void sendResponse(HttpExchange exchange, int httpCode, String contentType, String data) throws IOException {
     159        exchange.getResponseHeaders().set("Content-Type", contentType);
     160        exchange.getResponseHeaders().set("Server", "JOSM RemoteControl");
     161        exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
     162        exchange.sendResponseHeaders(httpCode, data.length());
     163        OutputStreamWriter out = new OutputStreamWriter(exchange.getResponseBody(), "UTF-8");
     164        out.write(data);
     165        out.close();
    46166    }
    47167}
  • src/org/openstreetmap/josm/io/remotecontrol/handler/AddNodeHandler.java

    diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/AddNodeHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/AddNodeHandler.java
    index 4ed5bc6..71f6c03 100644
    a b package org.openstreetmap.josm.io.remotecontrol.handler;  
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.util.Arrays;
    67import java.util.HashMap;
     8import java.util.List;
    79import org.openstreetmap.josm.Main;
    810import org.openstreetmap.josm.actions.AutoScaleAction;
    911import org.openstreetmap.josm.command.AddCommand;
    public class AddNodeHandler extends RequestHandler {  
    3032    }
    3133
    3234    @Override
     35    public String getUsage() {
     36        return "adds a node (given by its latitude and longitude) to the current dataset";
     37    }
     38
     39    @Override
     40    public List<String> getUsageExamples() {
     41        return Arrays.asList(
     42                "/add_node?lat=11&lon=22"
     43        );
     44    }
     45
     46    @Override
    3347    public String getPermissionMessage() {
    3448        return tr("Remote Control has been asked to create a new node.");
    3549    }
  • src/org/openstreetmap/josm/io/remotecontrol/handler/AddWayHandler.java

    diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/AddWayHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/AddWayHandler.java
    index c1cab8c..10e7188 100644
    a b package org.openstreetmap.josm.io.remotecontrol.handler;  
    22
    33import static org.openstreetmap.josm.tools.I18n.tr;
    44
     5import java.util.Arrays;
    56import java.util.LinkedList;
    67import java.util.List;
    78import org.openstreetmap.josm.Main;
    public class AddWayHandler extends RequestHandler {  
    2728    }
    2829
    2930    @Override
     31    public String getUsage() {
     32        return "adds a way (given by a semicolon separated sequence of lat,lon pairs) to the current dataset";
     33    }
     34
     35    @Override
     36    public List<String> getUsageExamples() {
     37        return Arrays.asList(
     38                "/add_way?way=lat1,lon2;lat2,lon2"
     39        );
     40    }
     41
     42    @Override
    3043    protected void handleRequest() throws RequestHandlerErrorException, RequestHandlerBadRequestException {
    3144        Way way = new Way();
    3245        List<Command> commands = new LinkedList<Command>();
  • src/org/openstreetmap/josm/io/remotecontrol/handler/ImageryHandler.java

    diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/ImageryHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/ImageryHandler.java
    index 1fdf8b0..7e9807a 100644
    a b import static org.openstreetmap.josm.tools.I18n.tr;  
    55
    66import java.io.UnsupportedEncodingException;
    77import java.net.URLDecoder;
     8import java.util.Arrays;
    89import java.util.HashMap;
     10import java.util.List;
    911
    1012import org.openstreetmap.josm.Main;
    1113import org.openstreetmap.josm.data.imagery.ImageryInfo;
    1214import org.openstreetmap.josm.gui.layer.ImageryLayer;
    1315import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
     16import org.openstreetmap.josm.tools.Utils;
    1417
    1518/**
    1619 * Adds an imagery (WMS/TMS) layer. For instance, {@code /imagery?title=...&type=...&url=...}.
    public class ImageryHandler extends RequestHandler {  
    3538    }
    3639
    3740    @Override
     41    public String getUsage() {
     42        return "adds an imagery layer (e.g. WMS, TMS))";
     43    }
     44
     45    @Override
     46    public List<String> getUsageExamples() {
     47        final String types = Utils.join("|", Utils.transform(Arrays.asList(ImageryInfo.ImageryType.values()), new Utils.Function<ImageryInfo.ImageryType, String>() {
     48            @Override
     49            public String apply(ImageryInfo.ImageryType x) {
     50                return x.getUrlString();
     51            }
     52        }));
     53        return Arrays.asList(
     54                "/imagery?title=...&type={"+types+"}&url=....[&cookies=...][&min_zoom=...][&max_zoom=...]"
     55        );
     56    }
     57
     58    @Override
    3859    public PermissionPrefWithDefault getPermissionPref() {
    3960        return PermissionPrefWithDefault.LOAD_IMAGERY;
    4061    }
  • src/org/openstreetmap/josm/io/remotecontrol/handler/ImportHandler.java

    diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/ImportHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/ImportHandler.java
    index 4175a51..57d436a 100644
    a b import static org.openstreetmap.josm.tools.I18n.tr;  
    55
    66import java.io.UnsupportedEncodingException;
    77import java.net.URLDecoder;
     8import java.util.Arrays;
    89import java.util.HashMap;
    910
     11import java.util.List;
    1012import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
    1113import org.openstreetmap.josm.actions.downloadtasks.DownloadTask;
    1214import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
    public class ImportHandler extends RequestHandler {  
    3638    }
    3739
    3840    @Override
     41    public String getUsage() {
     42        return "downloads the specified OSM file and adds it to the current data set";
     43    }
     44
     45    @Override
     46    public List<String> getUsageExamples() {
     47        return Arrays.asList(
     48                "/import?url=http://..."
     49        );
     50    }
     51
     52    @Override
    3953    public String getPermissionMessage() {
    4054        return tr("Remote Control has been asked to import data from the following URL:")
    4155                + "<br>" + request;
  • src/org/openstreetmap/josm/io/remotecontrol/handler/LoadAndZoomHandler.java

    diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/LoadAndZoomHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/LoadAndZoomHandler.java
    index fce910f..d0dc92b 100644
    a b import java.awt.geom.Area;  
    77import java.awt.geom.Rectangle2D;
    88import java.io.UnsupportedEncodingException;
    99import java.net.URLDecoder;
     10import java.util.Arrays;
    1011import java.util.HashSet;
     12import java.util.List;
    1113import java.util.Map;
    1214import java.util.concurrent.Future;
    1315
    public class LoadAndZoomHandler extends RequestHandler  
    5052    }
    5153
    5254    @Override
     55    public String getUsage() {
     56        return "download a bounding box from the API, zoom to the downloaded area and optionally select one or more objects";
     57    }
     58
     59    @Override
     60    public List<String> getUsageExamples() {
     61        return Arrays.asList(
     62                "/load_and_zoom?left=...&right=...&top=...&bottom=...[&select=object[,object...][&addtags=...][&zoom_mode=(download|selection)]]",
     63                "/zoom?left=...&right=...&top=...&bottom=...&select=object[,object...]"
     64        );
     65    }
     66
     67    @Override
    5368    protected void handleRequest() throws RequestHandlerErrorException
    5469    {
    5570        DownloadTask osmTask = new DownloadOsmTask();
  • src/org/openstreetmap/josm/io/remotecontrol/handler/LoadObjectHandler.java

    diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/LoadObjectHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/LoadObjectHandler.java
    index a1f25e7..3ca5edd 100644
    a b package org.openstreetmap.josm.io.remotecontrol.handler;  
    22
    33import static org.openstreetmap.josm.tools.I18n.tr;
    44
     5import java.util.Arrays;
    56import java.util.LinkedList;
    67import java.util.List;
    78import org.openstreetmap.josm.Main;
    public class LoadObjectHandler extends RequestHandler {  
    2526    }
    2627
    2728    @Override
     29    public String getUsage() {
     30        return "downloads the specified objects from the server";
     31    }
     32
     33    @Override
     34    public List<String> getUsageExamples() {
     35        return Arrays.asList(
     36                "/load_object?objects=n1,w2,r3[&new_layer=false][&relation_members=true]"
     37        );
     38    }
     39
     40    @Override
    2841    protected void handleRequest() throws RequestHandlerErrorException, RequestHandlerBadRequestException {
    2942        if (!PermissionPrefWithDefault.LOAD_DATA.isAllowed()) {
    3043            System.out.println("RemoteControl: download forbidden by preferences");
  • src/org/openstreetmap/josm/io/remotecontrol/handler/OpenFileHandler.java

    diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/OpenFileHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/OpenFileHandler.java
    index a049045..fd68783 100644
    a b package org.openstreetmap.josm.io.remotecontrol.handler;  
    22
    33import java.io.File;
    44import java.util.Arrays;
     5import java.util.List;
    56import org.openstreetmap.josm.actions.OpenFileAction;
    67import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
    78import static org.openstreetmap.josm.tools.I18n.tr;
    public class OpenFileHandler extends RequestHandler {  
    1617    }
    1718
    1819    @Override
     20    public String getUsage() {
     21        return "opens a local file in JOSM";
     22    }
     23
     24    @Override
     25    public List<String> getUsageExamples() {
     26        return Arrays.asList(
     27                "/open_file?filename=/tmp/test.osm"
     28        );
     29    }
     30
     31    @Override
    1932    public PermissionPrefWithDefault getPermissionPref() {
    2033        return PermissionPrefWithDefault.OPEN_FILES;
    2134    }
  • src/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandler.java

    diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandler.java
    index f920001..94b96c2 100644
    a b import java.text.MessageFormat;  
    99import java.util.HashMap;
    1010import java.util.LinkedList;
    1111import java.util.List;
    12 
    1312import javax.swing.JOptionPane;
    14 
    1513import org.openstreetmap.josm.Main;
    1614import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
    1715import org.openstreetmap.josm.tools.Utils;
    public abstract class RequestHandler {  
    9189
    9290    abstract public String[] getMandatoryParams();
    9391
     92    abstract public String getUsage();
     93
     94    abstract public List<String> getUsageExamples();
     95
    9496    /**
    9597     * Check permissions in preferences and display error message
    9698     * or ask for permission.
  • src/org/openstreetmap/josm/io/remotecontrol/handler/VersionHandler.java

    diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/VersionHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/VersionHandler.java
    index baf1783..cb0e6a3 100644
    a b package org.openstreetmap.josm.io.remotecontrol.handler;  
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.util.Arrays;
     7import java.util.List;
    68import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
    7 import org.openstreetmap.josm.io.remotecontrol.RequestProcessor;
     9import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
    810
    911/**
    1012 * Handler for version request.
    public class VersionHandler extends RequestHandler {  
    1618    @Override
    1719    protected void handleRequest() throws RequestHandlerErrorException,
    1820            RequestHandlerBadRequestException {
    19         content = RequestProcessor.PROTOCOLVERSION;
     21        content = RemoteControl.PROTOCOLVERSION;
    2022        contentType = "application/json";
    2123        if (args.containsKey("jsonp")) {
    2224            content = args.get("jsonp") + " && " + args.get("jsonp") + "(" + content + ")";
    public class VersionHandler extends RequestHandler {  
    3739    public String[] getMandatoryParams() {
    3840        return null;
    3941    }
     42
     43    @Override
     44    public String getUsage() {
     45        return "returns the current protocol version of the installed JOSM RemoteControl";
     46    }
     47
     48    @Override
     49    public List<String> getUsageExamples() {
     50        return Arrays.asList(
     51                "/version"
     52        );
     53    }
    4054}
     55 No newline at end of file