Changeset 23189 in osm for applications/editors/josm/plugins/remotecontrol/src
- Timestamp:
- 2010-09-15T18:53:09+02:00 (15 years ago)
- Location:
- applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol
- Files:
-
- 10 edited
-
PermissionPref.java (modified) (1 diff)
-
PermissionPrefWithDefault.java (modified) (2 diffs)
-
RemoteControlPlugin.java (modified) (4 diffs)
-
RequestHandler.java (modified) (8 diffs)
-
RequestHandlerForbiddenException.java (modified) (1 diff)
-
RequestProcessor.java (modified) (1 diff)
-
handler/AddNodeHandler.java (modified) (1 diff)
-
handler/ImportHandler.java (modified) (2 diffs)
-
handler/LoadAndZoomHandler.java (modified) (1 diff)
-
handler/VersionHandler.java (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/PermissionPref.java
r22733 r23189 7 7 * 8 8 * Use @see PermissionPrefWithDefault instead of this class. 9 * 9 * 10 10 * @author Bodo Meissner 11 11 */ 12 12 @Deprecated 13 13 public class PermissionPref { 14 /** name of the preference setting to permit the remote operation */15 String pref;16 /** message to be displayed if operation is not permitted */17 String message;18 19 public PermissionPref(String pref, String message)20 {21 this.pref = pref;22 this.message = message;23 }14 /** name of the preference setting to permit the remote operation */ 15 String pref; 16 /** message to be displayed if operation is not permitted */ 17 String message; 18 19 public PermissionPref(String pref, String message) 20 { 21 this.pref = pref; 22 this.message = message; 23 } 24 24 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/PermissionPrefWithDefault.java
r22733 r23189 2 2 3 3 /** 4 * This class should replace PermissionPref because it allows explicit 4 * This class should replace PermissionPref because it allows explicit 5 5 * specification of the permission's default value. 6 * 6 * 7 7 * @author Bodo Meissner 8 8 */ … … 10 10 public class PermissionPrefWithDefault extends PermissionPref { 11 11 12 boolean defaultVal = true;12 boolean defaultVal = true; 13 13 14 public PermissionPrefWithDefault(String pref, boolean defaultVal, String message) {15 super(pref, message);16 this.defaultVal = defaultVal;17 }14 public PermissionPrefWithDefault(String pref, boolean defaultVal, String message) { 15 super(pref, message); 16 this.defaultVal = defaultVal; 17 } 18 18 19 public PermissionPrefWithDefault(PermissionPref prefWithoutDefault) {20 super(prefWithoutDefault.pref, prefWithoutDefault.message);21 }19 public PermissionPrefWithDefault(PermissionPref prefWithoutDefault) { 20 super(prefWithoutDefault.pref, prefWithoutDefault.message); 21 } 22 22 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RemoteControlPlugin.java
r22733 r23189 8 8 9 9 /** 10 * Base plugin for remote control operations. 10 * Base plugin for remote control operations. 11 11 * This plugin contains operations that use JOSM core only. 12 * 13 * Other plugins can register additional operations by calling 12 * 13 * Other plugins can register additional operations by calling 14 14 * @see addRequestHandler(). 15 15 * To allow API changes this plugin contains a @see getVersion() method. 16 * 16 * 17 17 * IMPORTANT! increment the minor version on compatible API extensions 18 18 * and increment the major version and set minor to 0 on incompatible changes. … … 20 20 public class RemoteControlPlugin extends Plugin 21 21 { 22 /** API version23 * IMPORTANT! update the version number on API changes.24 */25 static final int apiMajorVersion = 1;26 static final int apiMinorVersion = 0;27 28 /**29 * RemoteControl HTTP protocol version. Change minor number for compatible30 * interface extensions. Change major number in case of incompatible31 * changes.32 */33 static final int protocolMajorVersion = 1;34 static final int protocolMinorVersion = 2;35 22 /** API version 23 * IMPORTANT! update the version number on API changes. 24 */ 25 static final int apiMajorVersion = 1; 26 static final int apiMinorVersion = 0; 27 28 /** 29 * RemoteControl HTTP protocol version. Change minor number for compatible 30 * interface extensions. Change major number in case of incompatible 31 * changes. 32 */ 33 static final int protocolMajorVersion = 1; 34 static final int protocolMinorVersion = 2; 35 36 36 /** The HTTP server this plugin launches */ 37 37 static HttpServer server; 38 38 39 39 /** 40 * Returns an array of int values with major and minor API version 40 * Returns an array of int values with major and minor API version 41 41 * and major and minor HTTP protocol version. 42 * 42 * 43 43 * The function returns an int[4] instead of an object with fields 44 44 * to avoid ClassNotFound errors with old versions of remotecontrol. 45 * 46 * @return array of integer version numbers: 45 * 46 * @return array of integer version numbers: 47 47 * apiMajorVersion, apiMinorVersion, protocolMajorVersion, protocolMajorVersion 48 48 */ 49 49 public int[] getVersion() 50 50 { 51 int versions[] = {apiMajorVersion, apiMinorVersion, protocolMajorVersion, protocolMajorVersion};52 return versions;51 int versions[] = {apiMajorVersion, apiMinorVersion, protocolMajorVersion, protocolMajorVersion}; 52 return versions; 53 53 } 54 54 55 55 /** 56 56 * Creates the plugin, and starts the HTTP server … … 58 58 public RemoteControlPlugin(PluginInformation info) 59 59 { 60 super(info);61 /*62 System.out.println("constructor " + this.getClass().getName() + " (" + info.name +63 " v " + info.version + " stage " + info.stage + ")");64 */60 super(info); 61 /* 62 System.out.println("constructor " + this.getClass().getName() + " (" + info.name + 63 " v " + info.version + " stage " + info.stage + ")"); 64 */ 65 65 restartServer(); 66 66 } … … 103 103 RequestProcessor.addRequestHandlerClass(command, handlerClass); 104 104 } 105 105 106 106 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RequestHandler.java
r22733 r23189 11 11 12 12 /** 13 * This is the parent of all classes that handle a specific command 13 * This is the parent of all classes that handle a specific command 14 14 * in remote control plug-in. 15 * 15 * 16 16 * @author Bodo Meissner 17 17 */ 18 18 public abstract class RequestHandler 19 19 { 20 public static final String globalConfirmationKey = "remotecontrol.always-confirm";21 public static final boolean globalConfirmationDefault = false;22 23 /** The GET request arguments */24 protected HashMap<String,String> args;25 26 /** The request URL without "GET". */20 public static final String globalConfirmationKey = "remotecontrol.always-confirm"; 21 public static final boolean globalConfirmationDefault = false; 22 23 /** The GET request arguments */ 24 protected HashMap<String,String> args; 25 26 /** The request URL without "GET". */ 27 27 protected String request; 28 28 … … 34 34 /** will be filled with the command assigned to the subclass */ 35 35 protected String myCommand; 36 36 37 37 /** 38 38 * Check permission and parameters and handle request. 39 * 39 * 40 40 * @throws RequestHandlerForbiddenException 41 41 * @throws RequestHandlerBadRequestException … … 44 44 final void handle() throws RequestHandlerForbiddenException, RequestHandlerBadRequestException, RequestHandlerErrorException 45 45 { 46 checkPermission();47 checkMandatoryParams();48 handleRequest();49 } 50 46 checkPermission(); 47 checkMandatoryParams(); 48 handleRequest(); 49 } 50 51 51 /** 52 52 * Handle a specific command sent as remote control. 53 * 54 * This method of the subclass will do the real work. 55 * 53 * 54 * This method of the subclass will do the real work. 55 * 56 56 * @throws RequestHandlerErrorException 57 * @throws RequestHandlerBadRequestException 57 * @throws RequestHandlerBadRequestException 58 58 */ 59 59 protected abstract void handleRequest() throws RequestHandlerErrorException, RequestHandlerBadRequestException; … … 62 62 * Get a specific message to ask the user for permission for the operation 63 63 * requested via remote control. 64 * 64 * 65 65 * This message will be displayed to the user if the preference 66 66 * remotecontrol.always-confirm is true. 67 * 67 * 68 68 * @return the message 69 69 */ … … 74 74 * preference to individually allow the requested operation and an error 75 75 * message to be displayed when a disabled operation is requested. 76 * 77 * Default is not to check any special preference. Override this in a 76 * 77 * Default is not to check any special preference. Override this in a 78 78 * subclass to define permission preference and error message. 79 * 79 * 80 80 * @return the preference name and error message or null 81 81 */ 82 @SuppressWarnings("deprecation")83 public PermissionPref getPermissionPref()82 @SuppressWarnings("deprecation") 83 public PermissionPref getPermissionPref() 84 84 { 85 85 /* Example: … … 93 93 protected String[] getMandatoryParams() 94 94 { 95 return null;96 } 97 98 /** 99 * Check permissions in preferences and display error message 95 return null; 96 } 97 98 /** 99 * Check permissions in preferences and display error message 100 100 * or ask for permission. 101 * 101 * 102 102 * @throws RequestHandlerForbiddenException 103 103 */ 104 104 @SuppressWarnings("deprecation") 105 final public void checkPermission() throws RequestHandlerForbiddenException106 { 107 /* 105 final public void checkPermission() throws RequestHandlerForbiddenException 106 { 107 /* 108 108 * If the subclass defines a specific preference and if this is set 109 109 * to false, abort with an error message. 110 * 110 * 111 111 * Note: we use the deprecated class here for compatibility with 112 112 * older versions of WMSPlugin. … … 118 118 if(permissionPref instanceof PermissionPrefWithDefault) 119 119 { 120 permissionPrefWithDefault = (PermissionPrefWithDefault) permissionPref;121 } 122 else 120 permissionPrefWithDefault = (PermissionPrefWithDefault) permissionPref; 121 } 122 else 123 123 { 124 permissionPrefWithDefault = new PermissionPrefWithDefault(permissionPref);124 permissionPrefWithDefault = new PermissionPrefWithDefault(permissionPref); 125 125 } 126 126 if (!Main.pref.getBoolean(permissionPrefWithDefault.pref, 127 permissionPrefWithDefault.defaultVal)) {127 permissionPrefWithDefault.defaultVal)) { 128 128 System.out.println(permissionPrefWithDefault.message); 129 129 throw new RequestHandlerForbiddenException(); … … 147 147 /** 148 148 * Set request URL and parse args. 149 * 149 * 150 150 * @param url The request URL. 151 151 */ 152 public void setUrl(String url) {153 this.request = url;154 parseArgs();155 }156 157 /**158 * Parse the request parameters as key=value pairs.159 * The result will be stored in this.args.160 * 161 * Can be overridden by subclass.162 */163 protected void parseArgs() {164 StringTokenizer st = new StringTokenizer(this.request, "&?");165 HashMap<String, String> args = new HashMap<String, String>();166 // ignore first token which is the command167 if(st.hasMoreTokens()) st.nextToken();168 while (st.hasMoreTokens()) {169 String param = st.nextToken();170 int eq = param.indexOf("=");171 if (eq > -1)172 args.put(param.substring(0, eq),152 public void setUrl(String url) { 153 this.request = url; 154 parseArgs(); 155 } 156 157 /** 158 * Parse the request parameters as key=value pairs. 159 * The result will be stored in this.args. 160 * 161 * Can be overridden by subclass. 162 */ 163 protected void parseArgs() { 164 StringTokenizer st = new StringTokenizer(this.request, "&?"); 165 HashMap<String, String> args = new HashMap<String, String>(); 166 // ignore first token which is the command 167 if(st.hasMoreTokens()) st.nextToken(); 168 while (st.hasMoreTokens()) { 169 String param = st.nextToken(); 170 int eq = param.indexOf("="); 171 if (eq > -1) 172 args.put(param.substring(0, eq), 173 173 param.substring(eq + 1)); 174 }175 this.args = args;176 }177 178 void checkMandatoryParams() throws RequestHandlerBadRequestException179 {180 String[] mandatory = getMandatoryParams();181 if(mandatory == null) return;182 183 boolean error = false;184 for(int i = 0; i < mandatory.length; ++i)185 {186 String key = mandatory[i];187 String value = args.get(key);188 if((value == null) || (value.length() == 0))189 {190 error = true;191 System.out.println("'" + myCommand + "' remote control request must have '" + key + "' parameter");192 }193 }194 if(error) throw new RequestHandlerBadRequestException();195 }196 197 /**198 * Save command associated with this handler.199 * 200 * @param command The command.201 */202 public void setCommand(String command)203 {204 if(command.charAt(0) == '/') command = command.substring(1);205 myCommand = command;206 }174 } 175 this.args = args; 176 } 177 178 void checkMandatoryParams() throws RequestHandlerBadRequestException 179 { 180 String[] mandatory = getMandatoryParams(); 181 if(mandatory == null) return; 182 183 boolean error = false; 184 for(int i = 0; i < mandatory.length; ++i) 185 { 186 String key = mandatory[i]; 187 String value = args.get(key); 188 if((value == null) || (value.length() == 0)) 189 { 190 error = true; 191 System.out.println("'" + myCommand + "' remote control request must have '" + key + "' parameter"); 192 } 193 } 194 if(error) throw new RequestHandlerBadRequestException(); 195 } 196 197 /** 198 * Save command associated with this handler. 199 * 200 * @param command The command. 201 */ 202 public void setCommand(String command) 203 { 204 if(command.charAt(0) == '/') command = command.substring(1); 205 myCommand = command; 206 } 207 207 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RequestHandlerForbiddenException.java
r22675 r23189 2 2 3 3 public class RequestHandlerForbiddenException extends RequestHandlerException { 4 private static final long serialVersionUID = 2263904699747115423L;4 private static final long serialVersionUID = 2263904699747115423L; 5 5 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RequestProcessor.java
r22734 r23189 23 23 */ 24 24 public class RequestProcessor extends Thread { 25 /**26 * RemoteControl protocol version. Change minor number for compatible27 * interface extensions. Change major number in case of incompatible28 * changes.29 */30 public static final String PROTOCOLVERSION = "{\"protocolversion\": {\"major\": " +31 RemoteControlPlugin.protocolMajorVersion + ", \"minor\": " +32 RemoteControlPlugin.protocolMinorVersion +33 "}, \"application\": \"JOSM RemoteControl\"}";34 35 /** The socket this processor listens on */36 private Socket request;37 38 /**39 * Collection of request handlers.40 * Will be initialized with default handlers here. Other plug-ins41 * can extend this list by using @see addRequestHandler42 */43 private static HashMap<String, Class<? extends RequestHandler>> handlers = new HashMap<String, Class<? extends RequestHandler>>();44 45 /**46 * Constructor47 * 48 * @param request A socket to read the request.49 */50 public RequestProcessor(Socket request) {51 super("RemoteControl request processor");52 this.setDaemon(true);53 this.request = request;54 }55 56 /**57 * Spawns a new thread for the request58 * 59 * @param request60 * The WMS request61 */62 public static void processRequest(Socket request) {63 RequestProcessor processor = new RequestProcessor(request);64 processor.start();65 }66 67 /**68 * Add external request handler. Can be used by other plug-ins that69 * want to use remote control.70 * @param command The command to handle.71 * @param handler The additional request handler.72 */73 static void addRequestHandlerClass(String command,74 Class<? extends RequestHandler> handler) {75 addRequestHandlerClass(command, handler, false);76 }77 78 /**79 * Add external request handler. Message can be suppressed.80 * (for internal use)81 * @param command The command to handle.82 * @param handler The additional request handler.83 * @param silent Don't show message if true.84 */85 private static void addRequestHandlerClass(String command,86 Class<? extends RequestHandler> handler, boolean silent) {87 if(command.charAt(0) == '/')88 {89 command = command.substring(1);90 }91 String commandWithSlash = "/" + command;92 if (handlers.get(commandWithSlash) != null) {93 System.out.println("RemoteControl: ignoring duplicate command " + command94 + " with handler " + handler.getName());95 } else {96 if(!silent) System.out.println("RemoteControl: adding command \"" +97 command + "\" (handled by " + handler.getSimpleName() + ")");98 handlers.put(commandWithSlash, handler);99 }100 }101 102 /** Add default request handlers */103 static {104 addRequestHandlerClass(LoadAndZoomHandler.command,105 LoadAndZoomHandler.class, true);106 addRequestHandlerClass(LoadAndZoomHandler.command2,107 LoadAndZoomHandler.class, true);108 addRequestHandlerClass(AddNodeHandler.command, AddNodeHandler.class, true);109 addRequestHandlerClass(ImportHandler.command, ImportHandler.class, true);110 addRequestHandlerClass(VersionHandler.command, VersionHandler.class, true);111 }112 113 /**114 * The work is done here.115 */116 public void run() {117 Writer out = null;118 try {119 OutputStream raw = new BufferedOutputStream(120 request.getOutputStream());121 out = new OutputStreamWriter(raw);122 Reader in = new InputStreamReader(new BufferedInputStream(123 request.getInputStream()), "ASCII");124 125 StringBuffer requestLine = new StringBuffer();126 while (requestLine.length() < 1024) {127 int c = in.read();128 if (c == '\r' || c == '\n')129 break;130 requestLine.append((char) c);131 }132 133 System.out.println("RemoteControl received: " + requestLine);134 String get = requestLine.toString();135 StringTokenizer st = new StringTokenizer(get);136 if (!st.hasMoreTokens()) {137 sendError(out);138 return;139 }140 String method = st.nextToken();141 if (!st.hasMoreTokens()) {142 sendError(out);143 return;144 }145 String url = st.nextToken();146 147 if (!method.equals("GET")) {148 sendNotImplemented(out);149 return;150 }151 152 String command = null;153 int questionPos = url.indexOf('?');154 if(questionPos < 0)155 {156 command = url;157 }158 else159 {160 command = url.substring(0, questionPos);161 }162 163 // find a handler for this command164 Class<? extends RequestHandler> handlerClass = handlers165 .get(command);166 if (handlerClass == null) {167 // no handler found168 sendBadRequest(out);169 } else {170 // create handler object171 RequestHandler handler = handlerClass.newInstance();172 try {173 handler.setCommand(command);174 handler.setUrl(url);175 handler.checkPermission();176 handler.handle();177 sendHeader(out, "200 OK", handler.contentType, false);178 out.write("Content-length: " + handler.content.length()179 + "\r\n");180 out.write("\r\n");181 out.write(handler.content);182 out.flush();183 } catch (RequestHandlerErrorException ex) {184 sendError(out);185 } catch (RequestHandlerBadRequestException ex) {186 sendBadRequest(out);187 } catch (RequestHandlerForbiddenException ex) {188 sendForbidden(out);189 }190 }191 192 } catch (IOException ioe) {193 } catch (Exception e) {194 e.printStackTrace();195 try {196 sendError(out);197 } catch (IOException e1) {198 }199 } finally {200 try {201 request.close();202 } catch (IOException e) {203 }204 }205 }206 207 /**208 * Sends a 500 error: server error209 * 210 * @param out211 * The writer where the error is written212 * @throws IOException213 * If the error can not be written214 */215 private void sendError(Writer out) throws IOException {216 sendHeader(out, "500 Internal Server Error", "text/html", true);217 out.write("<HTML>\r\n");218 out.write("<HEAD><TITLE>Internal Error</TITLE>\r\n");219 out.write("</HEAD>\r\n");220 out.write("<BODY>");221 out.write("<H1>HTTP Error 500: Internal Server Error</h2>\r\n");222 out.write("</BODY></HTML>\r\n");223 out.flush();224 }225 226 /**227 * Sends a 501 error: not implemented228 * 229 * @param out230 * The writer where the error is written231 * @throws IOException232 * If the error can not be written233 */234 private void sendNotImplemented(Writer out) throws IOException {235 sendHeader(out, "501 Not Implemented", "text/html", true);236 out.write("<HTML>\r\n");237 out.write("<HEAD><TITLE>Not Implemented</TITLE>\r\n");238 out.write("</HEAD>\r\n");239 out.write("<BODY>");240 out.write("<H1>HTTP Error 501: Not Implemented</h2>\r\n");241 out.write("</BODY></HTML>\r\n");242 out.flush();243 }244 245 /**246 * Sends a 403 error: forbidden247 * 248 * @param out249 * The writer where the error is written250 * @throws IOException251 * If the error can not be written252 */253 private void sendForbidden(Writer out) throws IOException {254 sendHeader(out, "403 Forbidden", "text/html", true);255 out.write("<HTML>\r\n");256 out.write("<HEAD><TITLE>Forbidden</TITLE>\r\n");257 out.write("</HEAD>\r\n");258 out.write("<BODY>");259 out.write("<H1>HTTP Error 403: Forbidden</h2>\r\n");260 out.write("</BODY></HTML>\r\n");261 out.flush();262 }263 264 /**265 * Sends a 403 error: forbidden266 * 267 * @param out268 * The writer where the error is written269 * @throws IOException270 * If the error can not be written271 */272 private void sendBadRequest(Writer out) throws IOException {273 sendHeader(out, "400 Bad Request", "text/html", true);274 out.write("<HTML>\r\n");275 out.write("<HEAD><TITLE>Bad Request</TITLE>\r\n");276 out.write("</HEAD>\r\n");277 out.write("<BODY>");278 out.write("<H1>HTTP Error 400: Bad Request</h2>\r\n");279 out.write("</BODY></HTML>\r\n");280 out.flush();281 }282 283 /**284 * Send common HTTP headers to the client.285 * 286 * @param out287 * The Writer288 * @param status289 * The status string ("200 OK", "500", etc)290 * @param contentType291 * The content type of the data sent292 * @param endHeaders293 * If true, adds a new line, ending the headers.294 * @throws IOException295 * When error296 */297 private void sendHeader(Writer out, String status, String contentType,298 boolean endHeaders) throws IOException {299 out.write("HTTP/1.1 " + status + "\r\n");300 Date now = new Date();301 out.write("Date: " + now + "\r\n");302 out.write("Server: JOSM RemoteControl\r\n");303 out.write("Content-type: " + contentType + "\r\n");304 out.write("Access-Control-Allow-Origin: *\r\n");305 if (endHeaders)306 out.write("\r\n");307 }25 /** 26 * RemoteControl protocol version. Change minor number for compatible 27 * interface extensions. Change major number in case of incompatible 28 * changes. 29 */ 30 public static final String PROTOCOLVERSION = "{\"protocolversion\": {\"major\": " + 31 RemoteControlPlugin.protocolMajorVersion + ", \"minor\": " + 32 RemoteControlPlugin.protocolMinorVersion + 33 "}, \"application\": \"JOSM RemoteControl\"}"; 34 35 /** The socket this processor listens on */ 36 private Socket request; 37 38 /** 39 * Collection of request handlers. 40 * Will be initialized with default handlers here. Other plug-ins 41 * can extend this list by using @see addRequestHandler 42 */ 43 private static HashMap<String, Class<? extends RequestHandler>> handlers = new HashMap<String, Class<? extends RequestHandler>>(); 44 45 /** 46 * Constructor 47 * 48 * @param request A socket to read the request. 49 */ 50 public RequestProcessor(Socket request) { 51 super("RemoteControl request processor"); 52 this.setDaemon(true); 53 this.request = request; 54 } 55 56 /** 57 * Spawns a new thread for the request 58 * 59 * @param request 60 * The WMS request 61 */ 62 public static void processRequest(Socket request) { 63 RequestProcessor processor = new RequestProcessor(request); 64 processor.start(); 65 } 66 67 /** 68 * Add external request handler. Can be used by other plug-ins that 69 * want to use remote control. 70 * @param command The command to handle. 71 * @param handler The additional request handler. 72 */ 73 static void addRequestHandlerClass(String command, 74 Class<? extends RequestHandler> handler) { 75 addRequestHandlerClass(command, handler, false); 76 } 77 78 /** 79 * Add external request handler. Message can be suppressed. 80 * (for internal use) 81 * @param command The command to handle. 82 * @param handler The additional request handler. 83 * @param silent Don't show message if true. 84 */ 85 private static void addRequestHandlerClass(String command, 86 Class<? extends RequestHandler> handler, boolean silent) { 87 if(command.charAt(0) == '/') 88 { 89 command = command.substring(1); 90 } 91 String commandWithSlash = "/" + command; 92 if (handlers.get(commandWithSlash) != null) { 93 System.out.println("RemoteControl: ignoring duplicate command " + command 94 + " with handler " + handler.getName()); 95 } else { 96 if(!silent) System.out.println("RemoteControl: adding command \"" + 97 command + "\" (handled by " + handler.getSimpleName() + ")"); 98 handlers.put(commandWithSlash, handler); 99 } 100 } 101 102 /** Add default request handlers */ 103 static { 104 addRequestHandlerClass(LoadAndZoomHandler.command, 105 LoadAndZoomHandler.class, true); 106 addRequestHandlerClass(LoadAndZoomHandler.command2, 107 LoadAndZoomHandler.class, true); 108 addRequestHandlerClass(AddNodeHandler.command, AddNodeHandler.class, true); 109 addRequestHandlerClass(ImportHandler.command, ImportHandler.class, true); 110 addRequestHandlerClass(VersionHandler.command, VersionHandler.class, true); 111 } 112 113 /** 114 * The work is done here. 115 */ 116 public void run() { 117 Writer out = null; 118 try { 119 OutputStream raw = new BufferedOutputStream( 120 request.getOutputStream()); 121 out = new OutputStreamWriter(raw); 122 Reader in = new InputStreamReader(new BufferedInputStream( 123 request.getInputStream()), "ASCII"); 124 125 StringBuffer requestLine = new StringBuffer(); 126 while (requestLine.length() < 1024) { 127 int c = in.read(); 128 if (c == '\r' || c == '\n') 129 break; 130 requestLine.append((char) c); 131 } 132 133 System.out.println("RemoteControl received: " + requestLine); 134 String get = requestLine.toString(); 135 StringTokenizer st = new StringTokenizer(get); 136 if (!st.hasMoreTokens()) { 137 sendError(out); 138 return; 139 } 140 String method = st.nextToken(); 141 if (!st.hasMoreTokens()) { 142 sendError(out); 143 return; 144 } 145 String url = st.nextToken(); 146 147 if (!method.equals("GET")) { 148 sendNotImplemented(out); 149 return; 150 } 151 152 String command = null; 153 int questionPos = url.indexOf('?'); 154 if(questionPos < 0) 155 { 156 command = url; 157 } 158 else 159 { 160 command = url.substring(0, questionPos); 161 } 162 163 // find a handler for this command 164 Class<? extends RequestHandler> handlerClass = handlers 165 .get(command); 166 if (handlerClass == null) { 167 // no handler found 168 sendBadRequest(out); 169 } else { 170 // create handler object 171 RequestHandler handler = handlerClass.newInstance(); 172 try { 173 handler.setCommand(command); 174 handler.setUrl(url); 175 handler.checkPermission(); 176 handler.handle(); 177 sendHeader(out, "200 OK", handler.contentType, false); 178 out.write("Content-length: " + handler.content.length() 179 + "\r\n"); 180 out.write("\r\n"); 181 out.write(handler.content); 182 out.flush(); 183 } catch (RequestHandlerErrorException ex) { 184 sendError(out); 185 } catch (RequestHandlerBadRequestException ex) { 186 sendBadRequest(out); 187 } catch (RequestHandlerForbiddenException ex) { 188 sendForbidden(out); 189 } 190 } 191 192 } catch (IOException ioe) { 193 } catch (Exception e) { 194 e.printStackTrace(); 195 try { 196 sendError(out); 197 } catch (IOException e1) { 198 } 199 } finally { 200 try { 201 request.close(); 202 } catch (IOException e) { 203 } 204 } 205 } 206 207 /** 208 * Sends a 500 error: server error 209 * 210 * @param out 211 * The writer where the error is written 212 * @throws IOException 213 * If the error can not be written 214 */ 215 private void sendError(Writer out) throws IOException { 216 sendHeader(out, "500 Internal Server Error", "text/html", true); 217 out.write("<HTML>\r\n"); 218 out.write("<HEAD><TITLE>Internal Error</TITLE>\r\n"); 219 out.write("</HEAD>\r\n"); 220 out.write("<BODY>"); 221 out.write("<H1>HTTP Error 500: Internal Server Error</h2>\r\n"); 222 out.write("</BODY></HTML>\r\n"); 223 out.flush(); 224 } 225 226 /** 227 * Sends a 501 error: not implemented 228 * 229 * @param out 230 * The writer where the error is written 231 * @throws IOException 232 * If the error can not be written 233 */ 234 private void sendNotImplemented(Writer out) throws IOException { 235 sendHeader(out, "501 Not Implemented", "text/html", true); 236 out.write("<HTML>\r\n"); 237 out.write("<HEAD><TITLE>Not Implemented</TITLE>\r\n"); 238 out.write("</HEAD>\r\n"); 239 out.write("<BODY>"); 240 out.write("<H1>HTTP Error 501: Not Implemented</h2>\r\n"); 241 out.write("</BODY></HTML>\r\n"); 242 out.flush(); 243 } 244 245 /** 246 * Sends a 403 error: forbidden 247 * 248 * @param out 249 * The writer where the error is written 250 * @throws IOException 251 * If the error can not be written 252 */ 253 private void sendForbidden(Writer out) throws IOException { 254 sendHeader(out, "403 Forbidden", "text/html", true); 255 out.write("<HTML>\r\n"); 256 out.write("<HEAD><TITLE>Forbidden</TITLE>\r\n"); 257 out.write("</HEAD>\r\n"); 258 out.write("<BODY>"); 259 out.write("<H1>HTTP Error 403: Forbidden</h2>\r\n"); 260 out.write("</BODY></HTML>\r\n"); 261 out.flush(); 262 } 263 264 /** 265 * Sends a 403 error: forbidden 266 * 267 * @param out 268 * The writer where the error is written 269 * @throws IOException 270 * If the error can not be written 271 */ 272 private void sendBadRequest(Writer out) throws IOException { 273 sendHeader(out, "400 Bad Request", "text/html", true); 274 out.write("<HTML>\r\n"); 275 out.write("<HEAD><TITLE>Bad Request</TITLE>\r\n"); 276 out.write("</HEAD>\r\n"); 277 out.write("<BODY>"); 278 out.write("<H1>HTTP Error 400: Bad Request</h2>\r\n"); 279 out.write("</BODY></HTML>\r\n"); 280 out.flush(); 281 } 282 283 /** 284 * Send common HTTP headers to the client. 285 * 286 * @param out 287 * The Writer 288 * @param status 289 * The status string ("200 OK", "500", etc) 290 * @param contentType 291 * The content type of the data sent 292 * @param endHeaders 293 * If true, adds a new line, ending the headers. 294 * @throws IOException 295 * When error 296 */ 297 private void sendHeader(Writer out, String status, String contentType, 298 boolean endHeaders) throws IOException { 299 out.write("HTTP/1.1 " + status + "\r\n"); 300 Date now = new Date(); 301 out.write("Date: " + now + "\r\n"); 302 out.write("Server: JOSM RemoteControl\r\n"); 303 out.write("Content-type: " + contentType + "\r\n"); 304 out.write("Access-Control-Allow-Origin: *\r\n"); 305 if (endHeaders) 306 out.write("\r\n"); 307 } 308 308 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/handler/AddNodeHandler.java
r22733 r23189 17 17 public class AddNodeHandler extends RequestHandler { 18 18 19 public static final String command = "add_node";20 public static final String permissionKey = "remotecontrol.permission.create-objects";21 public static final boolean permissionDefault = false;19 public static final String command = "add_node"; 20 public static final String permissionKey = "remotecontrol.permission.create-objects"; 21 public static final boolean permissionDefault = false; 22 22 23 @Override24 protected void handleRequest() {23 @Override 24 protected void handleRequest() { 25 25 addNode(args); 26 }26 } 27 27 28 @Override 29 protected String[] getMandatoryParams() 30 { 31 return new String[] { "lat", "lon" }; 32 } 33 34 @Override 35 public String getPermissionMessage() { 36 return tr("Remote Control has been asked to create a new node."); 37 } 28 @Override 29 protected String[] getMandatoryParams() 30 { 31 return new String[] { "lat", "lon" }; 32 } 38 33 39 @Override 40 public PermissionPrefWithDefault getPermissionPref() 41 { 42 return new PermissionPrefWithDefault(permissionKey, permissionDefault, 43 "RemoteControl: creating objects forbidden by preferences"); 44 } 45 34 @Override 35 public String getPermissionMessage() { 36 return tr("Remote Control has been asked to create a new node."); 37 } 38 39 @Override 40 public PermissionPrefWithDefault getPermissionPref() 41 { 42 return new PermissionPrefWithDefault(permissionKey, permissionDefault, 43 "RemoteControl: creating objects forbidden by preferences"); 44 } 45 46 46 /** 47 47 * Adds a node, implements the GET /add_node?lon=...&lat=... request. -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/handler/ImportHandler.java
r22733 r23189 16 16 public class ImportHandler extends RequestHandler { 17 17 18 public static final String command = "import";19 public static final String permissionKey = "remotecontrol.permission.import";20 public static final boolean permissionDefault = true;18 public static final String command = "import"; 19 public static final String permissionKey = "remotecontrol.permission.import"; 20 public static final boolean permissionDefault = true; 21 21 22 @Override23 protected void handleRequest() throws RequestHandlerErrorException {22 @Override 23 protected void handleRequest() throws RequestHandlerErrorException { 24 24 try { 25 25 DownloadTask osmTask = new DownloadOsmTask(); … … 30 30 throw new RequestHandlerErrorException(); 31 31 } 32 }32 } 33 33 34 @Override35 protected String[] getMandatoryParams()36 {37 return new String[] { "url" };38 }39 40 @Override41 public String getPermissionMessage() {42 return tr("Remote Control has been asked to import data from the following URL:") +34 @Override 35 protected String[] getMandatoryParams() 36 { 37 return new String[] { "url" }; 38 } 39 40 @Override 41 public String getPermissionMessage() { 42 return tr("Remote Control has been asked to import data from the following URL:") + 43 43 "<br>" + request; 44 }44 } 45 45 46 @Override47 public PermissionPrefWithDefault getPermissionPref()48 {49 return new PermissionPrefWithDefault(permissionKey, permissionDefault,50 "RemoteControl: import forbidden by preferences");51 }46 @Override 47 public PermissionPrefWithDefault getPermissionPref() 48 { 49 return new PermissionPrefWithDefault(permissionKey, permissionDefault, 50 "RemoteControl: import forbidden by preferences"); 51 } 52 52 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/handler/LoadAndZoomHandler.java
r22733 r23189 29 29 public class LoadAndZoomHandler extends RequestHandler 30 30 { 31 public static final String command = "load_and_zoom";32 public static final String command2 = "zoom";33 34 public static final String loadDataPermissionKey = "remotecontrol.permission.load-data";35 public static final boolean loadDataPermissionDefault = true;36 public static final String changeSelectionPermissionKey = "remotecontrol.permission.change-selection";37 public static final boolean changeSelectionPermissionDefault = true;38 public static final String changeViewportPermissionKey = "remotecontrol.permission.change-viewport";39 public static final boolean changeViewportPermissionDefault = true;40 31 public static final String command = "load_and_zoom"; 32 public static final String command2 = "zoom"; 33 34 public static final String loadDataPermissionKey = "remotecontrol.permission.load-data"; 35 public static final boolean loadDataPermissionDefault = true; 36 public static final String changeSelectionPermissionKey = "remotecontrol.permission.change-selection"; 37 public static final boolean changeSelectionPermissionDefault = true; 38 public static final String changeViewportPermissionKey = "remotecontrol.permission.change-viewport"; 39 public static final boolean changeViewportPermissionDefault = true; 40 41 41 @Override 42 42 public String getPermissionMessage() 43 43 { 44 return tr("Remote Control has been asked to load data from the API.") +44 return tr("Remote Control has been asked to load data from the API.") + 45 45 "<br>" + tr("Request details: {0}", request); 46 46 } 47 47 48 @Override 49 protected String[] getMandatoryParams() 50 { 51 return new String[] { "bottom", "top", "left", "right" }; 52 } 53 54 @Override 55 protected void handleRequest() throws RequestHandlerErrorException 56 { 57 DownloadTask osmTask = new DownloadOsmTask(); 58 double minlat = 0; 59 double maxlat = 0; 60 double minlon = 0; 61 double maxlon = 0; 62 try { 63 minlat = Double.parseDouble(args.get("bottom")); 64 maxlat = Double.parseDouble(args.get("top")); 65 minlon = Double.parseDouble(args.get("left")); 66 maxlon = Double.parseDouble(args.get("right")); 48 @Override 49 protected String[] getMandatoryParams() 50 { 51 return new String[] { "bottom", "top", "left", "right" }; 52 } 67 53 68 if(command.equals(myCommand)) 69 { 70 if (!Main.pref.getBoolean(loadDataPermissionKey, loadDataPermissionDefault)) 71 { 72 System.out.println("RemoteControl: download forbidden by preferences"); 73 } 74 else 75 { 76 77 // find out whether some data has already been downloaded 78 Area present = null; 79 Area toDownload = null; 80 DataSet ds = Main.main.getCurrentDataSet(); 81 if (ds != null) 82 present = ds.getDataSourceArea(); 83 if (present != null && !present.isEmpty()) { 84 toDownload = new Area(new Rectangle2D.Double(minlon,minlat,maxlon-minlon,maxlat-minlat)); 85 toDownload.subtract(present); 86 if (!toDownload.isEmpty()) 87 { 88 // the result might not be a rectangle (L shaped etc) 89 Rectangle2D downloadBounds = toDownload.getBounds2D(); 90 minlat = downloadBounds.getMinY(); 91 minlon = downloadBounds.getMinX(); 92 maxlat = downloadBounds.getMaxY(); 93 maxlon = downloadBounds.getMaxX(); 94 } 95 } 96 if((toDownload != null) && toDownload.isEmpty()) 97 { 98 System.out.println("RemoteControl: no download necessary"); 99 } 100 else 101 { 102 Future<?> future = osmTask.download(false /*no new layer*/, new Bounds(minlat,minlon,maxlat,maxlon), null /* let the task manage the progress monitor */); 103 Main.worker.submit(new PostDownloadHandler(osmTask, future)); 104 } 105 } 106 } 107 } catch (Exception ex) { 108 System.out.println("RemoteControl: Error parsing load_and_zoom remote control request:"); 109 ex.printStackTrace(); 110 throw new RequestHandlerErrorException(); 111 } 112 if (args.containsKey("select") && Main.pref.getBoolean(changeSelectionPermissionKey, changeSelectionPermissionDefault)) { 113 // select objects after downloading, zoom to selection. 114 final String selection = args.get("select"); 115 Main.worker.execute(new Runnable() { 116 public void run() { 117 HashSet<Long> ways = new HashSet<Long>(); 118 HashSet<Long> nodes = new HashSet<Long>(); 119 HashSet<Long> relations = new HashSet<Long>(); 120 HashSet<OsmPrimitive> newSel = new HashSet<OsmPrimitive>(); 121 for (String item : selection.split(",")) { 122 if (item.startsWith("way")) { 123 ways.add(Long.parseLong(item.substring(3))); 124 } else if (item.startsWith("node")) { 125 nodes.add(Long.parseLong(item.substring(4))); 126 } else if (item.startsWith("relation")) { 127 relations.add(Long.parseLong(item.substring(8))); 128 } else if (item.startsWith("rel")) { 129 relations.add(Long.parseLong(item.substring(3))); 130 } else { 131 System.out.println("RemoteControl: invalid selection '"+item+"' ignored"); 132 } 133 } 134 DataSet ds = Main.main.getCurrentDataSet(); 135 if(ds == null) // e.g. download failed 136 return; 137 for (Way w : ds.getWays()) if (ways.contains(w.getId())) newSel.add(w); 138 for (Node n : ds.getNodes()) if (nodes.contains(n.getId())) newSel.add(n); 139 for (Relation r : ds.getRelations()) if (relations.contains(r.getId())) newSel.add(r); 140 ds.setSelected(newSel); 141 if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault)) 142 new AutoScaleAction("selection").actionPerformed(null); 143 } 144 }); 145 } else if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault)) { 146 // after downloading, zoom to downloaded area. 147 zoom(minlat, maxlat, minlon, maxlon); 148 } 149 } 54 @Override 55 protected void handleRequest() throws RequestHandlerErrorException 56 { 57 DownloadTask osmTask = new DownloadOsmTask(); 58 double minlat = 0; 59 double maxlat = 0; 60 double minlon = 0; 61 double maxlon = 0; 62 try { 63 minlat = Double.parseDouble(args.get("bottom")); 64 maxlat = Double.parseDouble(args.get("top")); 65 minlon = Double.parseDouble(args.get("left")); 66 maxlon = Double.parseDouble(args.get("right")); 150 67 151 protected void zoom(double minlat, double maxlat, double minlon, double maxlon) { 152 final Bounds bounds = new Bounds(new LatLon(minlat, minlon), 153 new LatLon(maxlat, maxlon)); 68 if(command.equals(myCommand)) 69 { 70 if (!Main.pref.getBoolean(loadDataPermissionKey, loadDataPermissionDefault)) 71 { 72 System.out.println("RemoteControl: download forbidden by preferences"); 73 } 74 else 75 { 154 76 155 // make sure this isn't called unless there *is* a MapView 156 // 157 if (Main.map != null && Main.map.mapView != null) { 158 Main.worker.execute(new Runnable() { 159 public void run() { 160 BoundingXYVisitor bbox = new BoundingXYVisitor(); 161 bbox.visit(bounds); 162 Main.map.mapView.recalculateCenterScale(bbox); 163 } 164 }); 165 } 166 } 77 // find out whether some data has already been downloaded 78 Area present = null; 79 Area toDownload = null; 80 DataSet ds = Main.main.getCurrentDataSet(); 81 if (ds != null) 82 present = ds.getDataSourceArea(); 83 if (present != null && !present.isEmpty()) { 84 toDownload = new Area(new Rectangle2D.Double(minlon,minlat,maxlon-minlon,maxlat-minlat)); 85 toDownload.subtract(present); 86 if (!toDownload.isEmpty()) 87 { 88 // the result might not be a rectangle (L shaped etc) 89 Rectangle2D downloadBounds = toDownload.getBounds2D(); 90 minlat = downloadBounds.getMinY(); 91 minlon = downloadBounds.getMinX(); 92 maxlat = downloadBounds.getMaxY(); 93 maxlon = downloadBounds.getMaxX(); 94 } 95 } 96 if((toDownload != null) && toDownload.isEmpty()) 97 { 98 System.out.println("RemoteControl: no download necessary"); 99 } 100 else 101 { 102 Future<?> future = osmTask.download(false /*no new layer*/, new Bounds(minlat,minlon,maxlat,maxlon), null /* let the task manage the progress monitor */); 103 Main.worker.submit(new PostDownloadHandler(osmTask, future)); 104 } 105 } 106 } 107 } catch (Exception ex) { 108 System.out.println("RemoteControl: Error parsing load_and_zoom remote control request:"); 109 ex.printStackTrace(); 110 throw new RequestHandlerErrorException(); 111 } 112 if (args.containsKey("select") && Main.pref.getBoolean(changeSelectionPermissionKey, changeSelectionPermissionDefault)) { 113 // select objects after downloading, zoom to selection. 114 final String selection = args.get("select"); 115 Main.worker.execute(new Runnable() { 116 public void run() { 117 HashSet<Long> ways = new HashSet<Long>(); 118 HashSet<Long> nodes = new HashSet<Long>(); 119 HashSet<Long> relations = new HashSet<Long>(); 120 HashSet<OsmPrimitive> newSel = new HashSet<OsmPrimitive>(); 121 for (String item : selection.split(",")) { 122 if (item.startsWith("way")) { 123 ways.add(Long.parseLong(item.substring(3))); 124 } else if (item.startsWith("node")) { 125 nodes.add(Long.parseLong(item.substring(4))); 126 } else if (item.startsWith("relation")) { 127 relations.add(Long.parseLong(item.substring(8))); 128 } else if (item.startsWith("rel")) { 129 relations.add(Long.parseLong(item.substring(3))); 130 } else { 131 System.out.println("RemoteControl: invalid selection '"+item+"' ignored"); 132 } 133 } 134 DataSet ds = Main.main.getCurrentDataSet(); 135 if(ds == null) // e.g. download failed 136 return; 137 for (Way w : ds.getWays()) if (ways.contains(w.getId())) newSel.add(w); 138 for (Node n : ds.getNodes()) if (nodes.contains(n.getId())) newSel.add(n); 139 for (Relation r : ds.getRelations()) if (relations.contains(r.getId())) newSel.add(r); 140 ds.setSelected(newSel); 141 if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault)) 142 new AutoScaleAction("selection").actionPerformed(null); 143 } 144 }); 145 } else if (Main.pref.getBoolean(changeViewportPermissionKey, changeViewportPermissionDefault)) { 146 // after downloading, zoom to downloaded area. 147 zoom(minlat, maxlat, minlon, maxlon); 148 } 149 } 150 151 protected void zoom(double minlat, double maxlat, double minlon, double maxlon) { 152 final Bounds bounds = new Bounds(new LatLon(minlat, minlon), 153 new LatLon(maxlat, maxlon)); 154 155 // make sure this isn't called unless there *is* a MapView 156 // 157 if (Main.map != null && Main.map.mapView != null) { 158 Main.worker.execute(new Runnable() { 159 public void run() { 160 BoundingXYVisitor bbox = new BoundingXYVisitor(); 161 bbox.visit(bounds); 162 Main.map.mapView.recalculateCenterScale(bbox); 163 } 164 }); 165 } 166 } 167 167 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/handler/VersionHandler.java
r22733 r23189 14 14 public class VersionHandler extends RequestHandler { 15 15 16 public static final String command = "version";17 public static final String permissionKey = "remotecontrol.permission.read-protocolversion";18 public static final boolean permissionDefault = true;16 public static final String command = "version"; 17 public static final String permissionKey = "remotecontrol.permission.read-protocolversion"; 18 public static final boolean permissionDefault = true; 19 19 20 @Override21 protected void handleRequest() throws RequestHandlerErrorException,22 RequestHandlerBadRequestException {23 content = RequestProcessor.PROTOCOLVERSION;24 contentType = "application/json";25 if (args.containsKey("jsonp")) {26 content = args.get("jsonp")+ " && " + args.get("jsonp") + "(" + content + ")";27 }28 }20 @Override 21 protected void handleRequest() throws RequestHandlerErrorException, 22 RequestHandlerBadRequestException { 23 content = RequestProcessor.PROTOCOLVERSION; 24 contentType = "application/json"; 25 if (args.containsKey("jsonp")) { 26 content = args.get("jsonp")+ " && " + args.get("jsonp") + "(" + content + ")"; 27 } 28 } 29 29 30 @Override31 public String getPermissionMessage() {32 return tr("Remote Control has been asked to report its protocol version. This enables web sites to detect a running JOSM.");33 }30 @Override 31 public String getPermissionMessage() { 32 return tr("Remote Control has been asked to report its protocol version. This enables web sites to detect a running JOSM."); 33 } 34 34 35 @Override36 public PermissionPrefWithDefault getPermissionPref()37 {38 return new PermissionPrefWithDefault(permissionKey, permissionDefault,39 "RemoteControl: /version forbidden by preferences");40 }35 @Override 36 public PermissionPrefWithDefault getPermissionPref() 37 { 38 return new PermissionPrefWithDefault(permissionKey, permissionDefault, 39 "RemoteControl: /version forbidden by preferences"); 40 } 41 41 }
Note:
See TracChangeset
for help on using the changeset viewer.
