Changeset 12778 in osm for applications/editors/josm/plugins/remotecontrol
- Timestamp:
- 2009-01-01T18:28:53+01:00 (16 years ago)
- Location:
- applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/HttpServer.java
r9465 r12778 8 8 9 9 /** 10 * Simple HTTP server that spawns a {@link RequestProcessor} for every 10 * Simple HTTP server that spawns a {@link RequestProcessor} for every 11 11 * connection. 12 12 * … … 17 17 18 18 /** Default port for the HTTP server */ 19 public static final int DEFAULT_PORT = 8111; 20 21 /** The server socket */ 22 private ServerSocket server; 19 public static final int DEFAULT_PORT = 8111; 23 20 24 /** 25 * Constructor 26 * @param port The port this server will listen on 27 * @throws IOException when connection errors 28 */ 29 public HttpServer(int port) 30 throws IOException 31 { 32 super("RemoteControl HTTP Server"); 33 this.setDaemon(true); 34 // Start the server socket with only 1 connection. 21 /** The server socket */ 22 private ServerSocket server; 23 24 /** 25 * Constructor 26 * @param port The port this server will listen on 27 * @throws IOException when connection errors 28 */ 29 public HttpServer(int port) 30 throws IOException 31 { 32 super("RemoteControl HTTP Server"); 33 this.setDaemon(true); 34 // Start the server socket with only 1 connection. 35 35 // Also make sure we only listen 36 36 // on the local interface so nobody from the outside can connect! 37 37 this.server = new ServerSocket(port, 1, 38 38 InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 })); 39 39 } 40 40 41 42 43 44 45 46 47 48 49 try 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 41 /** 42 * The main loop, spawns a {@link RequestProcessor} for each connection 43 */ 44 public void run() 45 { 46 System.out.println("RemoteControl::Accepting connections on port " + server.getLocalPort()); 47 while (true) 48 { 49 try 50 { 51 Socket request = server.accept(); 52 RequestProcessor.processRequest(request); 53 } 54 catch( SocketException se) 55 { 56 if( !server.isClosed() ) 57 se.printStackTrace(); 58 } 59 catch (IOException ioe) 60 { 61 ioe.printStackTrace(); 62 } 63 } 64 } 65 66 /** 67 67 * Stops the HTTP server 68 * 68 * 69 69 * @throws IOException 70 71 72 73 74 70 */ 71 public void stopServer() throws IOException 72 { 73 server.close(); 74 } 75 75 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RemoteControlPlugin.java
r9417 r12778 12 12 public class RemoteControlPlugin extends Plugin 13 13 { 14 15 14 /** The HTTP server this plugin launches */ 15 static HttpServer server; 16 16 17 18 19 20 21 22 23 24 17 /** 18 * Creates the plugin, and starts the HTTP server 19 */ 20 public RemoteControlPlugin() 21 { 22 restartServer(); 23 } 24 25 25 @Override 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 26 public PreferenceSetting getPreferenceSetting() 27 { 28 return new RemoteControlPreferences(); 29 } 30 31 /** 32 * Starts or restarts the HTTP server 33 * 34 */ 35 public void restartServer() 36 { 37 try 38 { 39 if (server != null) 40 server.stopServer(); 41 42 int port = HttpServer.DEFAULT_PORT; 43 server = new HttpServer(port); 44 server.start(); 45 } 46 catch(IOException ioe) 47 { 48 ioe.printStackTrace(); 49 } 50 } 51 51 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RemoteControlPreferences.java
r12588 r12778 18 18 /** 19 19 * Preference settings for the Remote Control plugin 20 * 20 * 21 21 * @author Frederik Ramm 22 22 */ 23 23 public class RemoteControlPreferences implements PreferenceSetting 24 24 { 25 26 27 28 29 30 public void addGui(final PreferenceDialog gui) 25 private JCheckBox permissionLoadData = new JCheckBox(tr("load data from API")); 26 private JCheckBox permissionChangeSelection = new JCheckBox(tr("change the selection")); 27 private JCheckBox permissionChangeViewport = new JCheckBox(tr("change the viewport")); 28 private JCheckBox alwaysAskUserConfirm = new JCheckBox(tr("confirm all Remote Control actions manually")); 29 30 public void addGui(final PreferenceDialog gui) 31 31 { 32 33 34 35 36 37 38 32 Version ver = Util.getVersion(); 33 String description = tr("A plugin that allows JOSM to be controlled from other applications."); 34 if (ver != null) 35 description += "<br><br>" + tr("Version: {0}<br>Last change at {1}", ver.revision, ver.time) + "<br><br>"; 36 JPanel remote = gui.createPreferenceTab("remotecontrol.gif", tr("Remote Control"), tr("Settings for the Remote Control plugin.")); 37 remote.add(new JLabel("<html>"+tr("The Remote Control plugin will always listen on port 8111 on localhost." + 38 "The port is not variable because it is referenced by external applications talking to the plugin.") + "</html>"), GBC.eol().insets(0,5,0,10).fill(GBC.HORIZONTAL)); 39 39 40 41 42 40 JPanel perms = new JPanel(); 41 perms.setLayout(new GridBagLayout()); 42 perms.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray), tr("Permitted actions"))); 43 43 perms.add(permissionLoadData, GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL)); 44 44 perms.add(permissionChangeSelection, GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL)); 45 perms.add(permissionChangeViewport, GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL)); 45 perms.add(permissionChangeViewport, GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL)); 46 46 remote.add(perms, GBC.eol().fill(GBC.HORIZONTAL)); 47 47 48 48 remote.add(alwaysAskUserConfirm, GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL)); 49 49 remote.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL)); 50 50 51 51 52 52 permissionLoadData.setSelected(Main.pref.getBoolean("remotecontrol.permission.load-data", true)); 53 53 permissionChangeSelection.setSelected(Main.pref.getBoolean("remotecontrol.permission.change-selection", true)); 54 54 permissionChangeViewport.setSelected(Main.pref.getBoolean("remotecontrol.permission.change-viewport", true)); 55 55 alwaysAskUserConfirm.setSelected(Main.pref.getBoolean("remotecontrol.always-confirm", false)); 56 56 57 57 } 58 58 59 59 public boolean ok() { 60 61 62 63 64 60 Main.pref.put("remotecontrol.permission.load-data", permissionLoadData.isSelected()); 61 Main.pref.put("remotecontrol.permission.change-selection", permissionChangeSelection.isSelected()); 62 Main.pref.put("remotecontrol.permission.change-viewport", permissionChangeViewport.isSelected()); 63 Main.pref.put("remotecontrol.always-confirm", alwaysAskUserConfirm.isSelected()); 64 return false; 65 65 } 66 66 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RequestProcessor.java
r12431 r12778 30 30 * Processes HTTP "remote control" requests. 31 31 */ 32 public class RequestProcessor extends Thread 32 public class RequestProcessor extends Thread 33 33 { 34 35 36 37 38 39 40 41 42 43 * 44 45 46 47 48 49 50 51 52 53 54 55 * 56 57 58 59 60 61 62 } 63 64 65 66 67 68 69 70 try 71 {72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 34 /** The socket this processor listens on */ 35 private Socket request; 36 37 private class AlreadyLoadedException extends Exception {}; 38 private class DeniedException extends Exception {}; 39 private class LoadDeniedException extends Exception {}; 40 41 /** 42 * Constructor 43 * 44 * @param request 45 */ 46 public RequestProcessor(Socket request) 47 { 48 super("RemoteControl request processor"); 49 this.setDaemon(true); 50 this.request = request; 51 } 52 53 /** 54 * Spawns a new thread for the request 55 * 56 * @param request The WMS request 57 */ 58 public static void processRequest(Socket request) 59 { 60 RequestProcessor processor = new RequestProcessor(request); 61 processor.start(); 62 } 63 64 /** 65 * The work is done here. 66 */ 67 public void run() 68 { 69 Writer out = null; 70 try 71 { 72 OutputStream raw = new BufferedOutputStream( request.getOutputStream()); 73 out = new OutputStreamWriter(raw); 74 Reader in = new InputStreamReader(new BufferedInputStream(request.getInputStream()), "ASCII"); 75 76 StringBuffer requestLine = new StringBuffer(); 77 while (true) 78 { 79 int c = in.read(); 80 if (c == '\r' || c == '\n') break; 81 requestLine.append((char) c); 82 } 83 84 System.out.println("RemoteControl received: " + requestLine); 85 String get = requestLine.toString(); 86 StringTokenizer st = new StringTokenizer(get); 87 String method = st.nextToken(); 88 String url = st.nextToken(); 89 90 if(!method.equals("GET")) { 91 sendNotImplemented(out); 92 return; 93 } 94 94 95 95 st = new StringTokenizer(url, "&?"); 96 String command = null; 96 String command = null; 97 97 HashMap<String,String> args = new HashMap<String,String>(); 98 98 while (st.hasMoreTokens()) … … 106 106 } 107 107 } 108 108 109 109 if (command.equals("/load_and_zoom")) { 110 111 112 110 if (Main.pref.getBoolean("remotecontrol.always-confirm", false)) { 111 if (JOptionPane.showConfirmDialog(Main.parent, 112 "<html>" + tr("Remote Control has been asked to load data from the API.") + 113 113 "<br>" + tr("Request details: {0}", url) + "<br>" + tr("Do you want to allow this?"), 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 114 tr("Confirm Remote Control action"), 115 JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { 116 sendForbidden(out); 117 return; 118 } 119 } 120 DownloadTask osmTask = new DownloadOsmTask(); 121 if (!(args.containsKey("bottom") && args.containsKey("top") && 122 args.containsKey("left") && args.containsKey("right"))) { 123 sendBadRequest(out); 124 System.out.println("load_and_zoom remote control request must have bottom,top,left,right parameters"); 125 return; 126 } 127 double minlat = 0; 128 double maxlat = 0; 129 double minlon = 0; 130 double maxlon = 0; 131 try { 132 minlat = Double.parseDouble(args.get("bottom")); 133 maxlat = Double.parseDouble(args.get("top")); 134 minlon = Double.parseDouble(args.get("left")); 135 maxlon = Double.parseDouble(args.get("right")); 136 137 if (!Main.pref.getBoolean("remotecontrol.permission.load-data", true)) 138 throw new LoadDeniedException(); 139 140 // find out whether some data has already been downloaded 141 Area present = Main.ds.getDataSourceArea(); 142 if (present != null && !present.isEmpty()) { 143 Area toDownload = new Area(new Rectangle2D.Double(minlon,minlat,maxlon-minlon,maxlat-minlat)); 144 toDownload.subtract(present); 145 if (toDownload.isEmpty()) throw new AlreadyLoadedException(); 146 // the result might not be a rectangle (L shaped etc) 147 Rectangle2D downloadBounds = toDownload.getBounds2D(); 148 minlat = downloadBounds.getMinY(); 149 minlon = downloadBounds.getMinX(); 150 maxlat = downloadBounds.getMaxY(); 151 maxlon = downloadBounds.getMaxX(); 152 } 153 osmTask.download(null, minlat,minlon,maxlat,maxlon); 154 } catch (AlreadyLoadedException ex) { 155 System.out.println("RemoteControl: no download necessary"); 156 } catch (LoadDeniedException ex) { 157 System.out.println("RemoteControl: download forbidden by preferences"); 158 } catch (Exception ex) { 159 sendError(out); 160 System.out.println("RemoteControl: Error parsing load_and_zoom remote control request:"); 161 ex.printStackTrace(); 162 return; 163 } 164 if (args.containsKey("select") && Main.pref.getBoolean("remotecontrol.permission.change-selection", true)) { 165 // select objects after downloading, zoom to selection. 166 final String selection = args.get("select"); 167 Main.worker.execute(new Runnable() { 168 public void run() { 169 HashSet<Long> ways = new HashSet<Long>(); 170 HashSet<Long> nodes = new HashSet<Long>(); 171 HashSet<Long> relations = new HashSet<Long>(); 172 HashSet<OsmPrimitive> newSel = new HashSet<OsmPrimitive>(); 173 for (String item : selection.split(",")) { 174 if (item.startsWith("way")) { 175 ways.add(Long.parseLong(item.substring(3))); 176 } else if (item.startsWith("node")) { 177 nodes.add(Long.parseLong(item.substring(4))); 178 } else if (item.startsWith("relation")) { 179 relations.add(Long.parseLong(item.substring(8))); 180 } else { 181 System.out.println("RemoteControl: invalid selection '"+item+"' ignored"); 182 } 183 } 184 for (Way w : Main.ds.ways) if (ways.contains(w.id)) newSel.add(w); 185 for (Node n : Main.ds.nodes) if (nodes.contains(n.id)) newSel.add(n); 186 for (Relation r : Main.ds.relations) if (relations.contains(r.id)) newSel.add(r); 187 Main.ds.setSelected(newSel); 188 if (Main.pref.getBoolean("remotecontrol.permission.change-viewport", true)) 189 new AutoScaleAction("selection").actionPerformed(null); 190 } 191 }); 192 } else if (Main.pref.getBoolean("remotecontrol.permission.change-viewport", true)) { 193 // after downloading, zoom to downloaded area. 194 final LatLon min = new LatLon(minlat, minlon); 195 final LatLon max = new LatLon(maxlat, maxlon); 196 197 Main.worker.execute(new Runnable() { 198 public void run() { 199 BoundingXYVisitor bbox = new BoundingXYVisitor(); 200 bbox.min = Main.proj.latlon2eastNorth(min); 201 bbox.max = Main.proj.latlon2eastNorth(max); 202 Main.map.mapView.recalculateCenterScale(bbox); 203 } 204 }); 205 } 206 206 } else if (command.equals("/import")) { 207 208 209 210 "<br>" + url + 207 if (Main.pref.getBoolean("remotecontrol.always-confirm", false)) { 208 if (JOptionPane.showConfirmDialog(Main.parent, 209 "<html>" + tr("Remote Control has been asked to import data from the following URL:") + 210 "<br>" + url + 211 211 "<br>" + tr("Do you want to allow this?"), 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 212 tr("Confirm Remote Control action"), 213 JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { 214 sendForbidden(out); 215 return; 216 } 217 } 218 if (!(args.containsKey("url"))) { 219 sendBadRequest(out); 220 System.out.println("'import' remote control request must have url parameter"); 221 return; 222 } 223 try { 224 if (!Main.pref.getBoolean("remotecontrol.permission.import", true)) 225 throw new LoadDeniedException(); 226 227 DownloadTask osmTask = new DownloadOsmTask(); 228 osmTask.loadUrl(false, URLDecoder.decode(args.get("url"), "UTF-8")); 229 } catch (LoadDeniedException ex) { 230 System.out.println("RemoteControl: import forbidden by preferences"); 231 } catch (Exception ex) { 232 sendError(out); 233 System.out.println("RemoteControl: Error parsing import remote control request:"); 234 ex.printStackTrace(); 235 return; 236 } 237 237 // TODO: select/zoom to downloaded 238 238 } 239 239 sendHeader(out, "200 OK", "text/plain", false); 240 240 out.write("Content-length: 4\r\n"); 241 241 out.write("\r\n"); 242 242 out.write("OK\r\n"); 243 243 out.flush(); 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 * 328 329 330 331 332 333 334 335 336 337 338 244 } 245 catch (IOException ioe) { } 246 catch(Exception e) { 247 e.printStackTrace(); 248 try { 249 sendError(out); 250 } catch (IOException e1) { } 251 } finally { 252 try { 253 request.close(); 254 } catch (IOException e) {} 255 } 256 } 257 258 /** 259 * Sends a 500 error: server error 260 * @param out The writer where the error is written 261 * @throws IOException If the error can not be written 262 */ 263 private void sendError(Writer out) throws IOException 264 { 265 sendHeader(out, "500 Internal Server Error", "text/html", true); 266 out.write("<HTML>\r\n"); 267 out.write("<HEAD><TITLE>Internal Error</TITLE>\r\n"); 268 out.write("</HEAD>\r\n"); 269 out.write("<BODY>"); 270 out.write("<H1>HTTP Error 500: Internal Server Error</h2>\r\n"); 271 out.write("</BODY></HTML>\r\n"); 272 out.flush(); 273 } 274 275 /** 276 * Sends a 501 error: not implemented 277 * @param out The writer where the error is written 278 * @throws IOException If the error can not be written 279 */ 280 private void sendNotImplemented(Writer out) throws IOException 281 { 282 sendHeader(out, "501 Not Implemented", "text/html", true); 283 out.write("<HTML>\r\n"); 284 out.write("<HEAD><TITLE>Not Implemented</TITLE>\r\n"); 285 out.write("</HEAD>\r\n"); 286 out.write("<BODY>"); 287 out.write("<H1>HTTP Error 501: Not Implemented</h2>\r\n"); 288 out.write("</BODY></HTML>\r\n"); 289 out.flush(); 290 } 291 292 /** 293 * Sends a 403 error: forbidden 294 * @param out The writer where the error is written 295 * @throws IOException If the error can not be written 296 */ 297 private void sendForbidden(Writer out) throws IOException 298 { 299 sendHeader(out, "403 Forbidden", "text/html", true); 300 out.write("<HTML>\r\n"); 301 out.write("<HEAD><TITLE>Forbidden</TITLE>\r\n"); 302 out.write("</HEAD>\r\n"); 303 out.write("<BODY>"); 304 out.write("<H1>HTTP Error 403: Forbidden</h2>\r\n"); 305 out.write("</BODY></HTML>\r\n"); 306 out.flush(); 307 } 308 /** 309 * Sends a 403 error: forbidden 310 * @param out The writer where the error is written 311 * @throws IOException If the error can not be written 312 */ 313 private void sendBadRequest(Writer out) throws IOException 314 { 315 sendHeader(out, "400 Bad Request", "text/html", true); 316 out.write("<HTML>\r\n"); 317 out.write("<HEAD><TITLE>Bad Request</TITLE>\r\n"); 318 out.write("</HEAD>\r\n"); 319 out.write("<BODY>"); 320 out.write("<H1>HTTP Error 400: Bad Request</h2>\r\n"); 321 out.write("</BODY></HTML>\r\n"); 322 out.flush(); 323 } 324 325 /** 326 * Send common HTTP headers to the client. 327 * 328 * @param out The Writer 329 * @param status The status string ("200 OK", "500", etc) 330 * @param contentType The content type of the data sent 331 * @param endHeaders If true, adds a new line, ending the headers. 332 * @throws IOException When error 333 */ 334 private void sendHeader(Writer out, String status, String contentType, boolean endHeaders) throws IOException 335 { 336 out.write("HTTP/1.1 " + status + "\r\n"); 337 Date now = new Date(); 338 out.write("Date: " + now + "\r\n"); 339 339 out.write("Server: JOSM RemoteControl\r\n"); 340 340 out.write("Content-type: " + contentType + "\r\n"); 341 341 if (endHeaders) 342 343 342 out.write("\r\n"); 343 } 344 344 } -
applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/Util.java
r9465 r12778 17 17 /** 18 18 * Utility class 19 * 19 * 20 20 */ 21 public class Util 21 public class Util 22 22 { 23 23 /** 24 24 * Utility method to retrieve the plugin for classes that can't access to the plugin object directly. 25 * 25 * 26 26 * @param clazz The plugin class 27 27 * @return The YWMS plugin … … 29 29 public static Plugin getPlugin(Class<? extends Plugin> clazz) 30 30 { 31 31 String classname = clazz.getName(); 32 32 for (PluginProxy plugin : Main.plugins) 33 33 { … … 39 39 return null; 40 40 } 41 42 /**43 * Returns the plugin's directory of the plugin44 *45 * @return The directory of the plugin46 */47 public static String getPluginDir()48 {49 return Main.pref.getPreferencesDir() + "plugins/ywms/";50 }51 41 52 /** 53 * Returns the version 54 * @return The version of the application 55 */ 56 public static Version getVersion() 42 /** 43 * Returns the plugin's directory of the plugin 44 * 45 * @return The directory of the plugin 46 */ 47 public static String getPluginDir() 48 { 49 return Main.pref.getPreferencesDir() + "plugins/ywms/"; 50 } 51 52 /** 53 * Returns the version 54 * @return The version of the application 55 */ 56 public static Version getVersion() 57 57 { 58 58 PluginInformation info = PluginInformation.getLoaded("ywms"); 59 if (info == null) 59 if (info == null) 60 60 return null; 61 61 … … 65 65 /** 66 66 * Utility class for displaying versions 67 * 67 * 68 68 * @author frsantos 69 69 */ 70 70 public static class Version 71 71 { 72 73 74 75 76 72 /** The revision */ 73 public String revision; 74 /** The build time */ 75 public String time; 76 77 77 /** 78 78 * Constructor … … 80 80 * @param time 81 81 */ 82 public Version(String revision, String time) 82 public Version(String revision, String time) 83 83 { 84 85 86 84 this.revision = revision; 85 this.time = time; 86 } 87 87 } 88 88 }
Note:
See TracChangeset
for help on using the changeset viewer.