Index: src/mirrored_download/UrlSelectionAction.java
===================================================================
--- src/mirrored_download/UrlSelectionAction.java	(revision 28381)
+++ src/mirrored_download/UrlSelectionAction.java	(working copy)
@@ -1,27 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package mirrored_download;
-
-import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.event.ActionEvent;
-
-import org.openstreetmap.josm.actions.JosmAction;
-
-
-/**
- * TODO: Write comment.
- */
-public class UrlSelectionAction extends JosmAction {
-
-    public UrlSelectionAction() {
-        super(tr("Select OSM mirror URL"), (String)null, tr("Select OSM mirror URL to download from."),
-                null, true, "mirroreddownload/urlselection", true);
-        putValue("help", ht("/Action/SelectUrl"));
-    }
-
-    public void actionPerformed(ActionEvent e) {
-        UrlSelectionDialog dialog = UrlSelectionDialog.getInstance();
-        dialog.setVisible(true);
-    }
-}
Index: src/mirrored_download/UrlSelectionDialog.java
===================================================================
--- src/mirrored_download/UrlSelectionDialog.java	(revision 28381)
+++ src/mirrored_download/UrlSelectionDialog.java	(working copy)
@@ -1,179 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package mirrored_download;
-
-import static org.openstreetmap.josm.tools.I18n.marktr;
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Container;
-import java.awt.Frame;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.IOException;
-import java.text.DecimalFormat;
-import java.text.Format;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Vector;
-import java.util.zip.GZIPInputStream;
-
-import javax.swing.DefaultCellEditor;
-import javax.swing.DefaultListModel;
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JComponent;
-import javax.swing.JDialog;
-import javax.swing.JFileChooser;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTabbedPane;
-import javax.swing.JTable;
-import javax.swing.JTextField;
-import javax.swing.KeyStroke;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.event.TableModelEvent;
-import javax.swing.event.TableModelListener;
-import javax.swing.table.DefaultTableModel;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.JosmAction;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.ChangeCommand;
-import org.openstreetmap.josm.command.DeleteCommand;
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.gpx.GpxData;
-import org.openstreetmap.josm.data.gpx.GpxTrack;
-import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
-import org.openstreetmap.josm.data.gpx.WayPoint;
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
-import org.openstreetmap.josm.io.GpxReader;
-import org.openstreetmap.josm.io.MirroredInputStream;
-import org.openstreetmap.josm.tools.Utils;
-
-import org.xml.sax.SAXException;
-
-public class UrlSelectionDialog
-{
-  private JDialog jDialog = null;
-  private JTabbedPane tabbedPane = null;
-  private JComboBox cbSelectUrl = null;
-
-  public UrlSelectionDialog() {
-    Frame frame = JOptionPane.getFrameForComponent(Main.parent);
-    jDialog = new JDialog(frame, tr("Select OSM mirror URL"), false);
-    tabbedPane = new JTabbedPane();
-    JPanel tabSettings = new JPanel();
-    tabbedPane.addTab(tr("Settings"), tabSettings);
-    tabbedPane.setEnabledAt(0, true);
-    jDialog.add(tabbedPane);
-
-    //Settings Tab
-    JPanel contentPane = tabSettings;
-    GridBagLayout gridbag = new GridBagLayout();
-    GridBagConstraints layoutCons = new GridBagConstraints();
-    contentPane.setLayout(gridbag);
-
-    JLabel label = new JLabel(tr("Base URL"));
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 0;
-    layoutCons.gridwidth = 2;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(label, layoutCons);
-    contentPane.add(label);
-
-    cbSelectUrl = new JComboBox();
-    cbSelectUrl.setEditable(true);
-
-    String preferredUrl = Main.pref.get("plugin.mirrored_download.preferred-url");
-    if (preferredUrl != null && !"".equals(preferredUrl))
-      cbSelectUrl.addItem(preferredUrl);
-
-    for (String url: getURLs()) {
-      cbSelectUrl.addItem(url);
-    }
-
-    cbSelectUrl.setActionCommand("selectURL");
-    cbSelectUrl.addActionListener(new UrlChangedAction());
-
-    layoutCons.gridx = 0;
-    layoutCons.gridy = 1;
-    layoutCons.gridwidth = 1;
-    layoutCons.weightx = 0.0;
-    layoutCons.weighty = 0.0;
-    layoutCons.fill = GridBagConstraints.BOTH;
-    gridbag.setConstraints(cbSelectUrl, layoutCons);
-    contentPane.add(cbSelectUrl);
-
-    jDialog.pack();
-    jDialog.setLocationRelativeTo(frame);
-  }
-
-  private Collection<String> getURLs() {
-    // List can be edited at http://josm.openstreetmap.de/wiki/MirroredDownloadInfo
-    String src = Main.pref.get("plugin.mirrored_download.url-src", "http://josm.openstreetmap.de/mirrored_download_info");
-    Collection<String> urls = new ArrayList<String>();
-    InputStream in = null;
-    try {
-      in = new MirroredInputStream(src, 24*60*60);
-      BufferedReader reader = new BufferedReader(new InputStreamReader(in));
-      String line = null;
-      while ((line = reader.readLine()) != null) {
-        line = line.trim();
-        if (!line.equals("")) {
-          urls.add(line);
-        }
-      }
-    } catch (IOException e) {
-      e.printStackTrace();
-    }
-    Utils.close(in);
-    for (String url : Main.pref.getCollection("plugin.mirrored_download.custom-urls")) {
-      urls.add(url);
-    }
-    return urls;
-  }
-
-  public class UrlChangedAction implements ActionListener {
-
-    public void actionPerformed(ActionEvent e) {
-      MirroredDownloadPlugin.setDownloadUrl(cbSelectUrl.getSelectedItem().toString());
-      Main.pref.put("plugin.mirrored_download.preferred-url",
-          cbSelectUrl.getSelectedItem().toString());
-    }
-
-  }
-
-  public void setVisible(boolean visible) {
-    jDialog.setVisible(visible);
-  }
-
-  private static UrlSelectionDialog singleton = null;
-
-  public static UrlSelectionDialog getInstance() {
-
-    if (singleton == null)
-      singleton = new UrlSelectionDialog();
-
-    return singleton;
-  }
-}
Index: src/mirrored_download/MirroredDownloadAction.java
===================================================================
--- src/mirrored_download/MirroredDownloadAction.java	(revision 28381)
+++ src/mirrored_download/MirroredDownloadAction.java	(working copy)
@@ -6,19 +6,16 @@
 
 import java.awt.Component;
 import java.awt.GridBagConstraints;
-
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
+import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.concurrent.Future;
-import java.util.regex.Pattern;
 import javax.swing.JComboBox;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
-import javax.swing.text.JTextComponent;
 
 import org.openstreetmap.josm.actions.JosmAction;
-
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
 import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
@@ -27,7 +24,8 @@
 import org.openstreetmap.josm.data.osm.DataSource;
 import org.openstreetmap.josm.gui.download.DownloadDialog;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator;
+import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionItemPritority;
+import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionListItem;
 import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
 import org.openstreetmap.josm.io.BoundingBoxDownloader;
 import org.openstreetmap.josm.io.OsmTransferException;
@@ -36,11 +34,12 @@
 
 public class MirroredDownloadAction extends JosmAction {
 
+    static final String XAPI_SERVER_HISTORY_KEY = "plugin.mirrored_download.server-history";
+    static final String XAPI_DEFAULT_SERVER_KEY = "plugin.mirrored_download.server-default";
     static final String XAPI_QUERY_HISTORY_KEY = "plugin.mirrored_download.query-history";
-    static final String XAPI_QUERY_TOOLTIP = tr("XAPI query, e.g., '''' (to download all data), ''[highway=*]'', or ''[[network=VRR][ref=603|613]''");
 
     public MirroredDownloadAction() {
-        super(tr("Download from OSM mirror..."), (String)null, tr("Download map data from the OSM server."),
+        super(tr("Download from OSM mirror..."), (String) null, tr("Download map data from the OSM server."),
                 Shortcut.registerShortcut("mirror:download", tr("File: {0}", tr("Download from OSM mirror...")), KeyEvent.VK_DOWN, Shortcut.ALT_SHIFT),
                 true, "mirroreddownload/download", true);
         putValue("help", ht("/Action/MirroredDownload"));
@@ -56,38 +55,16 @@
             Bounds area = dialog.getSelectedDownloadArea();
             DownloadOsmTask task = new DownloadOsmTask();
             Future<?> future = task.download(
-                    new MirroredDownloadReader(area, dialog.getOverpassType(), dialog.getOverpassQuery()),
+                    new MirroredDownloadReader(area, dialog.getServerUrl(), dialog.getOverpassType(), dialog.getOverpassQuery()),
                     dialog.isNewLayerRequired(), area, null);
             Main.worker.submit(new PostDownloadHandler(task, future));
         }
     }
 
-    static class XAPIQueryValidator extends AbstractTextComponentValidator {
-
-        static final Pattern pattern = Pattern.compile("^(\\[([^=]+=[^=]*)\\])*$");
-
-        public XAPIQueryValidator(JTextComponent tc) throws IllegalArgumentException {
-            super(tc);
-        }
-
-        @Override
-        public void validate() {
-            if (pattern.matcher(getComponent().getText().trim()).matches()) {
-                feedbackValid(XAPI_QUERY_TOOLTIP);
-            } else {
-                feedbackInvalid(tr("This XAPI query seems to be invalid, please doublecheck"));
-            }
-        }
-
-        @Override
-        public boolean isValid() {
-            return pattern.matcher(getComponent().getText().trim()).matches();
-        }
-    }
-
     static class MirroredDownloadDialog extends DownloadDialog {
 
-        protected JComboBox/*<String>*/ overpassType;
+        protected HistoryComboBox serverUrl;
+        protected JComboBox overpassType;
         protected HistoryComboBox overpassQuery;
         private static MirroredDownloadDialog instance;
 
@@ -96,6 +73,7 @@
             cbDownloadOsmData.setEnabled(false);
             cbDownloadGpxData.setEnabled(false);
             cbStartup.setEnabled(false);
+            sizeCheck.setVisible(false);
         }
 
         static public MirroredDownloadDialog getInstance() {
@@ -107,28 +85,44 @@
 
         @Override
         protected void buildMainPanelAboveDownloadSelections(JPanel pnl) {
-            overpassType = new JComboBox/*<String>*/(new String[]{"*", "node", "way", "relation"});
+            overpassType = new JComboBox(new String[]{"*", "node", "way", "relation"});
             pnl.add(new JLabel(tr("Object type: ")), GBC.std().insets(5, 5, 5, 5));
             pnl.add(overpassType, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
             overpassType.setToolTipText(tr("OSM object type to download (''*'' stands for any)"));
+            serverUrl = new HistoryComboBox();
+            pnl.add(new JLabel(tr("Server URL: ")), GBC.std().insets(5, 5, 5, 5));
+            pnl.add(serverUrl, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
+            serverUrl.setToolTipText(tr("OSM mirror URL to download from"));
             overpassQuery = new HistoryComboBox();
-            pnl.add(new JLabel(tr("XAPI query: ")), GBC.std().insets(5, 5, 5, 5));
-            new XAPIQueryValidator((JTextComponent) overpassQuery.getEditor().getEditorComponent());
+            pnl.add(new JLabel(tr("Query: ")), GBC.std().insets(5, 5, 5, 5));
             pnl.add(overpassQuery, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
-            overpassQuery.setToolTipText(XAPI_QUERY_TOOLTIP);
+            overpassQuery.setToolTipText(tr("XAPI query, e.g., '''' (to download all data), ''[highway=*]'', or ''[[network=VRR][ref=603|613]''"));
         }
 
+        public String getServerUrl() {
+            return serverUrl.getText();
+        }
+
         public String getOverpassQuery() {
             return overpassQuery.getText();
         }
 
         public String getOverpassType() {
-            return (String)overpassType.getItemAt(overpassType.getSelectedIndex());
+            return (String) overpassType.getItemAt(overpassType.getSelectedIndex());
         }
 
         @Override
         public void restoreSettings() {
             super.restoreSettings();
+            serverUrl.setPossibleItems(
+                    Main.pref.getCollection(XAPI_SERVER_HISTORY_KEY, new LinkedList<String>()));
+            for (String s : Main.pref.getCollection(XAPI_DEFAULT_SERVER_KEY, Arrays.asList(
+                    "http://ovehttp://rpass.osm.rambler.ru/cgi/xapi?{type}[bbox={xapi_bbox}][@meta]",
+                    "http://overpass-api.de/api/xapi?{type}[bbox={xapi_bbox}][@meta]"))) {
+                serverUrl.addItem(new AutoCompletionListItem(s, AutoCompletionItemPritority.IS_IN_STANDARD));
+            }
+            serverUrl.setSelectedIndex(1);
+            serverUrl.setSelectedIndex(0);
             overpassQuery.setPossibleItems(
                     Main.pref.getCollection(XAPI_QUERY_HISTORY_KEY, new LinkedList<String>()));
         }
@@ -136,6 +130,8 @@
         @Override
         public void rememberSettings() {
             super.rememberSettings();
+            serverUrl.addCurrentItemToHistory();
+            Main.pref.putCollection(XAPI_SERVER_HISTORY_KEY, serverUrl.getHistory());
             overpassQuery.addCurrentItemToHistory();
             Main.pref.putCollection(XAPI_QUERY_HISTORY_KEY, overpassQuery.getHistory());
         }
@@ -143,25 +139,32 @@
 
     static class MirroredDownloadReader extends BoundingBoxDownloader {
 
+        final String serverUrl;
         final String overpassType;
         final String overpassQuery;
 
-        public MirroredDownloadReader(Bounds downloadArea, String overpassType, String overpassQuery) {
+        public MirroredDownloadReader(Bounds downloadArea, String serverUrl, String overpassType, String overpassQuery) {
             super(downloadArea);
+            this.serverUrl = serverUrl;
             this.overpassType = overpassType;
             this.overpassQuery = overpassQuery.trim();
         }
 
         @Override
         protected String getBaseUrl() {
-            return MirroredDownloadPlugin.getDownloadUrl();
+            return null;
         }
 
         @Override
         protected String getRequestForBbox(double lon1, double lat1, double lon2, double lat2) {
-            return overpassQuery.isEmpty() && "*".equals(overpassType)
-                    ? super.getRequestForBbox(lon1, lat1, lon2, lat2)
-                    : overpassType + "[bbox=" + lon1 + "," + lat1 + "," + lon2 + "," + lat2 + "][@meta]" + overpassQuery;
+            return ((serverUrl + overpassQuery)
+                    .replace("{type}", overpassType)
+                    .replace("{xapi_bbox}", "{minlon},{minlat},{maxlon},{maxlat}")
+                    .replace("{overpass_bbox}", "{minlat},{minlon},{maxlat},{maxlon}"))
+                    .replace("{minlon}", Double.toString(lon1))
+                    .replace("{minlat}", Double.toString(lat1))
+                    .replace("{maxlon}", Double.toString(lon2))
+                    .replace("{maxlat}", Double.toString(lat2));
         }
 
         @Override
@@ -173,15 +176,15 @@
             if (ds != null && ds.dataSources.isEmpty()) {
                 if (crosses180th) {
                     Bounds bounds = new Bounds(lat1, lon1, lat2, 180.0);
-                    DataSource src = new DataSource(bounds, MirroredDownloadPlugin.getDownloadUrl());
+                    DataSource src = new DataSource(bounds, serverUrl);
                     ds.dataSources.add(src);
 
                     bounds = new Bounds(lat1, -180.0, lat2, lon2);
-                    src = new DataSource(bounds, MirroredDownloadPlugin.getDownloadUrl());
+                    src = new DataSource(bounds, serverUrl);
                     ds.dataSources.add(src);
                 } else {
                     Bounds bounds = new Bounds(lat1, lon1, lat2, lon2);
-                    DataSource src = new DataSource(bounds, MirroredDownloadPlugin.getDownloadUrl());
+                    DataSource src = new DataSource(bounds, serverUrl);
                     ds.dataSources.add(src);
                 }
             }
Index: src/mirrored_download/MirroredDownloadPlugin.java
===================================================================
--- src/mirrored_download/MirroredDownloadPlugin.java	(revision 28381)
+++ src/mirrored_download/MirroredDownloadPlugin.java	(working copy)
@@ -11,15 +11,5 @@
     public MirroredDownloadPlugin(PluginInformation info) {
         super(info);
         MainMenu.addAfter(Main.main.menu.fileMenu, new MirroredDownloadAction(), false, Main.main.menu.download);
-        MainMenu.add(Main.main.menu.editMenu, new UrlSelectionAction());
     }
-    private static String downloadUrl = "http://overpass.osm.rambler.ru/cgi/xapi?";//"http://overpass-api.de/api/xapi?";
-
-    public static String getDownloadUrl() {
-        return downloadUrl;
-    }
-
-    public static void setDownloadUrl(String downloadUrl_) {
-        downloadUrl = downloadUrl_;
-    }
 }
