Changeset 9465 in osm for applications/editors


Ignore:
Timestamp:
2008-08-05T02:28:44+02:00 (16 years ago)
Author:
frederik
Message:
  • remote control plugin for JOSM is now usable.
Location:
applications/editors/josm/plugins/remotecontrol
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/remotecontrol/README

    r9417 r9465  
    1 A plugin for JOSM that listens for commands on a TCP port. It can be used to
    2 tell JOSM to zoom to an area and download data.
     1A plugin for JOSM that listens for commands on a TCP port (8111).
     2It can be used to tell JOSM to zoom to an area and download data.
     3Details are found on the Wiki page,
     4
     5http://wiki.openstreetmap.org/index.php/JOSM/Plugins/RemoteControl
     6
     7Initially written by Frederik Ramm <frederik@remote.org>. License:
     8GPL V2 or later. Incorporates code taken from YWMS plugin by frsantos.
     9
  • applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/HttpServer.java

    r9417 r9465  
    88
    99/**
    10  * Simple HTTP server that spawns a {@link RequestProcessor} for every connection.
    11  *
    12  * @author frsantos
    13   */
    14 public class HttpServer extends Thread
    15 {
     10 * Simple HTTP server that spawns a {@link RequestProcessor} for every
     11 * connection.
     12 *
     13 * Taken from YWMS plugin by frsantos.
     14 */
     15
     16public class HttpServer extends Thread {
     17
    1618    /** Default port for the HTTP server */
    1719        public static final int DEFAULT_PORT = 8111;
  • applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RemoteControlPreferences.java

    r9417 r9465  
    33import static org.openstreetmap.josm.tools.I18n.tr;
    44
     5import java.awt.Color;
     6import java.awt.GridBagLayout;
    57import java.awt.event.*;
    68
    79import javax.swing.*;
    810
     11import org.openstreetmap.josm.Main;
    912import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
    1013import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
    1114import org.openstreetmap.josm.plugins.remotecontrol.Util.Version;
     15import org.openstreetmap.josm.tools.GBC;
    1216import org.openstreetmap.josm.tools.I18n;
    1317
     
    1923public class RemoteControlPreferences implements PreferenceSetting
    2024{
    21 
    22    
    23     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)
    2431    {
    25  
    2632                Version ver = Util.getVersion();
    2733                String description = tr("A plugin that allows JOSM to be controlled from other applications.");
    28                 if( ver != null )
     34                if (ver != null)
    2935                        description += "<br><br>" + tr("Version: {0}<br>Last change at {1}", ver.revision, ver.time) + "<br><br>";
    30         JPanel ywms = gui.createPreferenceTab("remotecontrol.gif", I18n.tr("Remote Control"), description + I18n.tr("Settings for the Remote Control plugin."));
    31         ywms.add(new JLabel("no prefs yet."));
     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
     40        JPanel perms = new JPanel();
     41        perms.setLayout(new GridBagLayout());
     42        perms.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray), tr("Permitted actions")));
     43        perms.add(permissionLoadData, GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL));
     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));       
     46        remote.add(perms, GBC.eol().fill(GBC.HORIZONTAL));
     47       
     48        remote.add(alwaysAskUserConfirm, GBC.eol().insets(0,5,0,0).fill(GBC.HORIZONTAL));
     49        remote.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
     50
     51       
     52        permissionLoadData.setSelected(Main.pref.getBoolean("remotecontrol.permission.load-data", true));
     53        permissionChangeSelection.setSelected(Main.pref.getBoolean("remotecontrol.permission.change-selection", true));
     54        permissionChangeViewport.setSelected(Main.pref.getBoolean("remotecontrol.permission.change-viewport", true));
     55        alwaysAskUserConfirm.setSelected(Main.pref.getBoolean("remotecontrol.always-confirm", false));
     56       
    3257    }
    3358   
    3459    public void ok() {
    35     }
    36 
    37     /**
    38      * ActionListener for the configuration of WMS plugin 
    39      * @author frsantos
    40      */
    41     private final class RemoteControlConfigurationActionListener implements ActionListener, FocusListener
    42     {
    43         /** If the action is already handled */
    44         boolean alreadyHandled = false;
    45         public void actionPerformed(ActionEvent e) {
    46             if(!alreadyHandled)
    47                 configureRemoteControlPluginPreferences();
    48             alreadyHandled = true;
    49         }
    50 
    51         public void focusGained(FocusEvent e) {
    52             alreadyHandled = false;
    53         }
    54 
    55         public void focusLost(FocusEvent e) {
    56             if(!alreadyHandled)
    57                 configureRemoteControlPluginPreferences();
    58             alreadyHandled = true;
    59         }
    60     }
    61    
    62    
    63     /**
    64      * Configures Remote Control
    65      */
    66     private void configureRemoteControlPluginPreferences()
    67     {
     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               
    6865    }
    6966}
  • applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/RequestProcessor.java

    r9417 r9465  
    11package org.openstreetmap.josm.plugins.remotecontrol;
    22
     3import static org.openstreetmap.josm.tools.I18n.tr;
     4
     5import java.awt.geom.Area;
     6import java.awt.geom.Rectangle2D;
    37import java.io.*;
    48import java.net.Socket;
     
    812import java.util.StringTokenizer;
    913
     14import javax.swing.JOptionPane;
     15
    1016import org.openstreetmap.josm.Main;
     17import org.openstreetmap.josm.actions.AutoScaleAction;
    1118import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
     19import org.openstreetmap.josm.data.coor.EastNorth;
     20import org.openstreetmap.josm.data.coor.LatLon;
    1221import org.openstreetmap.josm.data.osm.Node;
    1322import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1423import org.openstreetmap.josm.data.osm.Relation;
    1524import org.openstreetmap.josm.data.osm.Way;
     25import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
    1626import org.openstreetmap.josm.gui.download.DownloadDialog.DownloadTask;
    1727
     
    2333        /** The socket this processor listens on */
    2434        private Socket request;
     35       
     36        private class AlreadyLoadedException extends Exception {};
     37        private class DeniedException extends Exception {};
     38        private class LoadDeniedException extends Exception {};
    2539 
    2640        /**
     
    7387                String url = st.nextToken();
    7488
    75                 if( !method.equals("GET") )
    76                 {
     89                if(!method.equals("GET")) {
    7790                        sendNotImplemented(out);
    7891                        return;
     
    8598            {
    8699                String param = st.nextToken();
    87                 if (command == null)
    88                 {
     100                if (command == null) {
    89101                    command = param;
    90                 }
    91                 else
    92                 {
     102                } else {
    93103                    int eq = param.indexOf("=");
    94                     if (eq>-1)
    95                         args.put(param.substring(0,eq), param.substring(eq+1));
     104                    if (eq>-1) args.put(param.substring(0,eq), param.substring(eq+1));
    96105                }
    97106            }
    98107           
    99108            if (command.equals("/load_and_zoom")) {
    100                                 DownloadTask osmTask = new DownloadOsmTask();
     109                if (Main.pref.getBoolean("remotecontrol.always-confirm", false)) {
     110                        if (JOptionPane.showConfirmDialog(Main.parent,
     111                                tr("Remote Control has been asked to load data from the API. Request details: {0}. Do you want to allow this?", url),
     112                                tr("Confirm Remote Control action"),
     113                                JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {
     114                                        sendForbidden(out);
     115                                        return;
     116                        }
     117                }
     118                DownloadTask osmTask = new DownloadOsmTask();
    101119                                if (!(args.containsKey("bottom") && args.containsKey("top") &&
    102120                                        args.containsKey("left") && args.containsKey("right"))) {
    103                                         sendError(out);
     121                                        sendBadRequest(out);
    104122                                        System.out.println("load_and_zoom remote control request must have bottom,top,left,right parameters");
    105123                                        return;
    106124                                }
     125                                double minlat = 0;
     126                                double maxlat = 0;
     127                                double minlon = 0;
     128                                double maxlon = 0;
    107129                                try {
    108                                         double minlat = Double.parseDouble(args.get("bottom"));
    109                                         double maxlat = Double.parseDouble(args.get("top"));
    110                                         double minlon = Double.parseDouble(args.get("left"));
    111                                         double maxlon = Double.parseDouble(args.get("right"));
    112                                         osmTask.download(Main.main.menu.download, minlat,minlon,maxlat,maxlon);
    113                                 }
    114                                 catch (Exception ex)
    115                                 {
     130                                        minlat = Double.parseDouble(args.get("bottom"));
     131                                        maxlat = Double.parseDouble(args.get("top"));
     132                                        minlon = Double.parseDouble(args.get("left"));
     133                                        maxlon = Double.parseDouble(args.get("right"));
     134                                       
     135                                        if (!Main.pref.getBoolean("remotecontrol.permission.load-data", true))
     136                                                throw new LoadDeniedException();
     137                                       
     138                                        // find out whether some data has already been downloaded
     139                                        Area present = Main.ds.getDataSourceArea();
     140                                        if (present != null && !present.isEmpty()) {
     141                                                Area toDownload = new Area(new Rectangle2D.Double(minlon,minlat,maxlon-minlon,maxlat-minlat));
     142                                                toDownload.subtract(present);
     143                                                if (toDownload.isEmpty()) throw new AlreadyLoadedException();
     144                                                // the result might not be a rectangle (L shaped etc)
     145                                                Rectangle2D downloadBounds = toDownload.getBounds2D();
     146                                                minlat = downloadBounds.getMinY();
     147                                                minlon = downloadBounds.getMinX();
     148                                                maxlat = downloadBounds.getMaxY();
     149                                                maxlon = downloadBounds.getMaxX();
     150                                        }
     151                                        osmTask.download(null, minlat,minlon,maxlat,maxlon);
     152                                } catch (AlreadyLoadedException ex) {
     153                                        System.out.println("RemoteControl: no download necessary");
     154                                } catch (LoadDeniedException ex) {
     155                                        System.out.println("RemoteControl: download forbidden by preferences");
     156                                } catch (Exception ex) {
    116157                                        sendError(out);
    117158                                        System.out.println("RemoteControl: Error parsing load_and_zoom remote control request:");
     
    119160                                        return;
    120161                                }
    121                                 if (args.containsKey("select")) {
     162                                if (args.containsKey("select") && Main.pref.getBoolean("remotecontrol.permission.change-selection", true)) {
     163                                        // select objects after downloading, zoom to selection.
    122164                                        final String selection = args.get("select");
    123165                                        Main.worker.execute(new Runnable() {
     
    142184                                                        for (Relation r : Main.ds.relations) if (relations.contains(r.id)) newSel.add(r);       
    143185                                                        Main.ds.setSelected(newSel);
     186                                                        if (Main.pref.getBoolean("remotecontrol.permission.change-viewport", true))
     187                                                                new AutoScaleAction("selection").actionPerformed(null);
    144188                                                }
    145189                                        });
    146                                 };
     190                                } else if (Main.pref.getBoolean("remotecontrol.permission.change-viewport", true)) {
     191                                        // after downloading, zoom to downloaded area.
     192                                        final LatLon min = new LatLon(minlat, minlon);
     193                                        final LatLon max = new LatLon(maxlat, maxlon);
     194                                       
     195                                        Main.worker.execute(new Runnable() {
     196                                                public void run() {
     197                                                        BoundingXYVisitor bbox = new BoundingXYVisitor();
     198                                                        bbox.min = Main.proj.latlon2eastNorth(min);
     199                                                        bbox.max = Main.proj.latlon2eastNorth(max);
     200                                                        Main.map.mapView.recalculateCenterScale(bbox);
     201                                                }
     202                                        });
     203                                }
    147204            }
    148205                        sendHeader(out, "200 OK", "text/plain", false);
     
    153210                }
    154211                catch (IOException ioe) { }
    155                 catch(Exception e)
    156                 {
     212                catch(Exception e) {
    157213                        e.printStackTrace();
    158                         try
    159                         {
     214                        try {
    160215                                sendError(out);
    161                         }
    162                         catch (IOException e1) { }
    163                 }
    164                 finally
    165                 {
    166                 try
    167                 {
     216                        } catch (IOException e1) { }
     217                } finally {
     218                try {
    168219                        request.close();       
    169                 }
    170                 catch (IOException e) {}
     220                } catch (IOException e) {}
    171221                }
    172222        }
     
    205255                out.flush();
    206256        }
     257
     258        /**
     259         * Sends a 403 error: forbidden
     260         * @param out The writer where the error is written
     261         * @throws IOException If the error can not be written
     262         */
     263        private void sendForbidden(Writer out) throws IOException
     264        {
     265                sendHeader(out, "403 Forbidden", "text/html", true);
     266                out.write("<HTML>\r\n");
     267                out.write("<HEAD><TITLE>Forbidden</TITLE>\r\n");
     268                out.write("</HEAD>\r\n");
     269                out.write("<BODY>");
     270                out.write("<H1>HTTP Error 403: Forbidden</h2>\r\n");
     271                out.write("</BODY></HTML>\r\n");
     272                out.flush();
     273        }
     274        /**
     275         * Sends a 403 error: forbidden
     276         * @param out The writer where the error is written
     277         * @throws IOException If the error can not be written
     278         */
     279        private void sendBadRequest(Writer out) throws IOException
     280        {
     281                sendHeader(out, "400 Bad Request", "text/html", true);
     282                out.write("<HTML>\r\n");
     283                out.write("<HEAD><TITLE>Bad Request</TITLE>\r\n");
     284                out.write("</HEAD>\r\n");
     285                out.write("<BODY>");
     286                out.write("<H1>HTTP Error 400: Bad Request</h2>\r\n");
     287                out.write("</BODY></HTML>\r\n");
     288                out.flush();
     289        }
    207290       
    208291        /**
  • applications/editors/josm/plugins/remotecontrol/src/org/openstreetmap/josm/plugins/remotecontrol/Util.java

    r9417 r9465  
    1818 * Utility class
    1919 *
    20  * @author frsantos
    2120 */
    2221public class Util
    2322{
    24 
    2523    /**
    2624     * Utility method to retrieve the plugin for classes that can't access to the plugin object directly.
     
    3432        for (PluginProxy plugin : Main.plugins)
    3533        {
    36             if( plugin.info.className.equals(classname) )
     34            if(plugin.info.className.equals(classname))
    3735            {
    3836                return (Plugin)plugin.plugin;
    3937            }
    4038        }
    41        
    4239        return null;
    4340    }
     
    5451
    5552        /**
    56          * Utility method for creating buttons
    57          * @param name The name of the button
    58          * @param icon Icon of the button
    59          * @param tooltip Tooltip
    60          * @param action The action performed when clicking the button
    61          * @return The created button
    62          */
    63     public static JButton createButton(String name, String icon, String tooltip, ActionListener action)
    64     {
    65                 JButton button = new JButton(tr(name), ImageProvider.get(icon));
    66                 button.setActionCommand(name);
    67                 button.addActionListener(action);
    68                 button.setToolTipText(tr(tooltip));
    69                 button.putClientProperty("help", "Dialog/SelectionList/" + name);
    70                 return button;
    71         }
    72    
    73    
    74         /**
    7553         * Returns the version
    7654         * @return The version of the application
     
    7957    {
    8058        PluginInformation info = PluginInformation.getLoaded("ywms");
    81         if( info == null )
     59        if (info == null)
    8260            return null;
    8361
     
    10886                }
    10987    }
    110    
    111    
    112     /**
    113      * Loads a text file in a String
    114      *
    115      * @param resource The URL of the file
    116      * @return A String with the file contents
    117      * @throws IOException when error reading the file
    118      */
    119     public static String loadFile(URL resource) throws IOException
    120     {
    121         BufferedReader in = null;
    122                 try
    123                 {
    124                         in = new BufferedReader(new InputStreamReader(resource.openStream()));
    125                         StringBuilder sb = new StringBuilder();
    126                         for (String line = in.readLine(); line != null; line = in.readLine())
    127                         {
    128                                 sb.append(line);
    129                                 sb.append('\n');
    130                         }
    131                         return sb.toString();
    132                 }
    133                 finally
    134                 {
    135                         if( in != null )
    136                         {
    137                                 try {
    138                                         in.close();
    139                                 } catch (IOException e) {
    140                                         e.printStackTrace();
    141                                 }
    142                         }
    143                 }
    144     }
    145    
    146     /**
    147      * Mirrors a file to a local file.
    148      * <p>
    149      * The file mirrored is only downloaded if it has been more than one day since last download
    150      *
    151      * @param url The URL of the remote file
    152      * @param destDir The destionation dir of the mirrored file
    153      * @param maxTime The time interval, in seconds, to check if the file changed. If less than 0, it defaults to 1 week
    154      * @return The local file
    155      */
    156     public static File mirror(URL url, String destDir, long maxTime)
    157     {
    158         if( url.getProtocol().equals("file") )
    159             return new File(url.toString() ) ;
    160        
    161         String localPath = Main.pref.get("tests.mirror." + url);
    162         File oldFile = null;
    163         if( localPath != null && localPath.length() > 0)
    164         {
    165             StringTokenizer st = new StringTokenizer(localPath, ";");
    166             long checkDate = Long.parseLong(st.nextToken());
    167             localPath = st.nextToken();
    168             oldFile = new File(localPath);
    169             maxTime = (maxTime <= 0) ? 7 * 24 * 60 * 60 * 1000 : maxTime * 1000;
    170             if( System.currentTimeMillis() - checkDate < maxTime )
    171             {
    172                 if( oldFile.exists() )
    173                     return oldFile;
    174             }
    175         }
    176 
    177         File destDirFile = new File(destDir);
    178         if( !destDirFile.exists() )
    179             destDirFile.mkdirs();
    180 
    181         localPath = destDir + System.currentTimeMillis() + "-" + new File(url.getPath()).getName();
    182         BufferedOutputStream bos = null;
    183         BufferedInputStream bis = null;
    184         try
    185         {
    186             URLConnection conn = url.openConnection();
    187             conn.setConnectTimeout(5000);
    188             bis = new BufferedInputStream(conn.getInputStream());
    189             bos = new BufferedOutputStream( new FileOutputStream(localPath) );
    190             byte[] buffer = new byte[4096];
    191             int length;
    192             while( (length = bis.read( buffer )) > -1 )
    193             {
    194                 bos.write( buffer, 0, length );
    195             }
    196         }
    197         catch(IOException ioe)
    198         {
    199             if( oldFile != null )
    200                 return oldFile;
    201             else
    202                 return null;
    203         }
    204         finally
    205         {
    206             if( bis != null )
    207             {
    208                 try {
    209                     bis.close();
    210                 } catch (IOException e) {
    211                     e.printStackTrace();
    212                 }
    213             }
    214             if( bos != null )
    215             {
    216                 try {
    217                     bos.close();
    218                 } catch (IOException e) {
    219                     e.printStackTrace();
    220                 }
    221             }
    222         }
    223        
    224         Main.pref.put("tests.mirror." + url, System.currentTimeMillis() + ";" + localPath);
    225        
    226         if( oldFile != null )
    227             oldFile.delete();
    228 
    229         return new File(localPath);
    230     }
    231    
    232         /**
    233          * Copies the ressource 'from' to the file in the plugin directory named 'to'.
    234          * @param from The source directory
    235          * @param to The destination directory
    236          * @throws FileNotFoundException
    237          * @throws IOException
    238          */
    239         public static void copy(String from, String to) throws FileNotFoundException, IOException {
    240                 File pluginDir = new File(getPluginDir());
    241                 if (!pluginDir.exists())
    242                         pluginDir.mkdirs();
    243         FileOutputStream out = new FileOutputStream(getPluginDir()+to);
    244         InputStream in = Util.class.getResourceAsStream(from);
    245         byte[] buffer = new byte[8192];
    246         for(int len = in.read(buffer); len > 0; len = in.read(buffer))
    247                 out.write(buffer, 0, len);
    248         in.close();
    249         out.close();
    250     }
    25188}
Note: See TracChangeset for help on using the changeset viewer.