Index: /trunk/src/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTask.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTask.java	(revision 7472)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTask.java	(revision 7473)
@@ -11,4 +11,5 @@
 
 import javax.swing.JOptionPane;
+import javax.xml.parsers.ParserConfigurationException;
 
 import org.openstreetmap.josm.Main;
@@ -16,20 +17,15 @@
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.help.HelpUtil;
-import org.openstreetmap.josm.io.IllegalDataException;
-import org.openstreetmap.josm.io.OsmChangesetParser;
+import org.openstreetmap.josm.io.Capabilities;
 import org.openstreetmap.josm.io.OsmTransferException;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Utils;
+import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
 /**
  * This is an asynchronous task for testing whether an URL points to an OSM API server.
- * It tries to retrieve a list of changesets from the given URL. If it succeeds, the method
+ * It tries to retrieve capabilities from the given URL. If it succeeds, the method
  * {@link #isSuccess()} replies true, otherwise false.
- *
- * Note: it fetches a list of changesets instead of the much smaller capabilities because - strangely enough -
- * an OSM server "https://x.y.y/api/0.6" not only responds to  "https://x.y.y/api/0.6/capabilities" but also
- * to "https://x.y.y/api/0/capabilities" or "https://x.y.y/a/capabilities" with valid capabilities. If we get
- * valid capabilities with an URL we therefore can't be sure that the base URL is valid API URL.
  * @since 2745
  */
@@ -71,5 +67,5 @@
     }
 
-    protected void alertInvalidChangesetUrl(String url) {
+    protected void alertInvalidCapabilitiesUrl(String url) {
         HelpAwareOptionPane.showMessageDialogInEDT(
                 parent,
@@ -120,5 +116,5 @@
     }
 
-    protected void alertInvalidChangesetList() {
+    protected void alertInvalidCapabilities() {
         HelpAwareOptionPane.showMessageDialogInEDT(
                 parent,
@@ -150,6 +146,5 @@
 
     /**
-     * Removes leading and trailing whitespace from the API URL and removes trailing
-     * '/'.
+     * Removes leading and trailing whitespace from the API URL and removes trailing '/'.
      *
      * @return the normalized API URL
@@ -173,9 +168,9 @@
             }
             URL capabilitiesUrl;
-            String getChangesetsUrl = getNormalizedApiUrl() + "/0.6/changesets";
+            String getCapabilitiesUrl = getNormalizedApiUrl() + "/0.6/capabilities";
             try {
-                capabilitiesUrl = new URL(getChangesetsUrl);
+                capabilitiesUrl = new URL(getCapabilitiesUrl);
             } catch(MalformedURLException e) {
-                alertInvalidChangesetUrl(getChangesetsUrl);
+                alertInvalidCapabilitiesUrl(getCapabilitiesUrl);
                 return;
             }
@@ -195,13 +190,9 @@
 
             try {
-                OsmChangesetParser.parse(connection.getInputStream(), progressMonitor.createSubTaskMonitor(1, true));
-            } catch (IllegalDataException e) {
-                if (e.getCause() instanceof IOException) {
-                    throw (IOException) e.getCause();
-                } else {
-                    Main.warn(e.getMessage());
-                    alertInvalidChangesetList();
-                    return;
-                }
+                Capabilities.CapabilitiesParser.parse(new InputSource(connection.getInputStream()));
+            } catch (SAXException | ParserConfigurationException e) {
+                Main.warn(e.getMessage());
+                alertInvalidCapabilities();
+                return;
             }
             success = true;
Index: /trunk/src/org/openstreetmap/josm/io/Capabilities.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/Capabilities.java	(revision 7472)
+++ /trunk/src/org/openstreetmap/josm/io/Capabilities.java	(revision 7473)
@@ -4,4 +4,5 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -10,8 +11,15 @@
 import java.util.Map;
 
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
 import org.openstreetmap.josm.Main;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
 
 /**
- * Represents the server capabilities
+ * Represents the OSM API server capabilities.
  *
  * Example capabilites document:
@@ -43,6 +51,6 @@
 public class Capabilities {
 
-    private Map<String, HashMap<String,String>> capabilities;
-    private List<String> imageryBlacklist;
+    private final Map<String, HashMap<String,String>> capabilities;
+    private final List<String> imageryBlacklist;
 
     /**
@@ -50,7 +58,15 @@
      */
     public Capabilities() {
-        clear();
-    }
-
+        capabilities = new HashMap<>();
+        imageryBlacklist = new ArrayList<>();
+    }
+
+    /**
+     * Determines if given element and attribute are defined.
+     *
+     * @param element the name of the element
+     * @param attribute the name of the attribute
+     * @return {@code true} if defined, {@code false} otherwise
+     */
     public boolean isDefined(String element, String attribute) {
         if (! capabilities.containsKey(element)) return false;
@@ -60,5 +76,12 @@
     }
 
-    public String get(String element, String attribute ) {
+    /**
+     * Returns the value of configuration item in the capabilities as string value.
+     *
+     * @param element the name of the element
+     * @param attribute the name of the attribute
+     * @return the value; {@code null}, if the respective configuration item does not exist
+     */
+    public String get(String element, String attribute) {
         if (! capabilities.containsKey(element)) return null;
         HashMap<String, String> e = capabilities.get(element);
@@ -68,11 +91,10 @@
 
     /**
-     * returns the value of configuration item in the capabilities as
-     * double value
-     *
-     * @param element  the name of the element
-     * @param attribute the name of the attribute
-     * @return the value; null, if the respective configuration item doesn't exist
-     * @throws NumberFormatException  if the value is not a valid double
+     * Returns the value of configuration item in the capabilities as double value.
+     *
+     * @param element the name of the element
+     * @param attribute the name of the attribute
+     * @return the value; {@code null}, if the respective configuration item does not exist
+     * @throws NumberFormatException if the value is not a valid double
      */
     public Double getDouble(String element, String attribute) throws NumberFormatException {
@@ -82,4 +104,12 @@
     }
 
+    /**
+     * Returns the value of configuration item in the capabilities as long value.
+     *
+     * @param element the name of the element
+     * @param attribute the name of the attribute
+     * @return the value; {@code null}, if the respective configuration item does not exist
+     * @throws NumberFormatException if the value is not a valid long
+     */
     public Long getLong(String element, String attribute) {
         String s = get(element, attribute);
@@ -88,4 +118,11 @@
     }
 
+    /**
+     * Adds a new configuration item.
+     *
+     * @param element the name of the element
+     * @param attribute the name of the attribute
+     * @param value the value as string
+     */
     public void put(String element, String attribute, String value) {
         if ("blacklist".equals(element)) {
@@ -103,9 +140,17 @@
     }
 
+    /**
+     * Clears the API capabilities.
+     */
     public final void clear() {
-        capabilities = new HashMap<>();
-        imageryBlacklist = new ArrayList<>();
-    }
-
+        capabilities.clear();
+        imageryBlacklist.clear();
+    }
+
+    /**
+     * Determines if a given API version is supported.
+     * @param version The API version to check
+     * @return {@code true} is version is between the minimum supported version and the maximum one, {@code false} otherwise
+     */
     public boolean supportsVersion(String version) {
         return get("version", "minimum").compareTo(version) <= 0
@@ -137,10 +182,9 @@
 
     /**
-     * checks if the given URL is blacklisted by one of the of the
-     * regular expressions.
-     */
-
-    public boolean isOnImageryBlacklist(String url)
-    {
+     * Checks if the given URL is blacklisted by one of the of the regular expressions.
+     * @param url Imagery URL to check
+     * @return {@code true} if URL is blacklisted, {@code false} otherwise
+     */
+    public boolean isOnImageryBlacklist(String url) {
         if (url != null && imageryBlacklist != null) {
             for (String blacklistRegex : imageryBlacklist) {
@@ -153,9 +197,53 @@
 
     /**
-     * returns the full list of blacklist regular expressions.
-     */
-    public List<String> getImageryBlacklist()
-    {
+     * Returns the full list of imagery blacklist regular expressions.
+     * @return full list of imagery blacklist regular expressions
+     */
+    public List<String> getImageryBlacklist() {
         return Collections.unmodifiableList(imageryBlacklist);
     }
+
+    /**
+     * A parser for the "capabilities" response XML.
+     * @since 7473
+     */
+    public static final class CapabilitiesParser extends DefaultHandler {
+
+        private Capabilities capabilities;
+
+        @Override
+        public void startDocument() throws SAXException {
+            capabilities = new Capabilities();
+        }
+
+        @Override
+        public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
+            for (int i=0; i< atts.getLength(); i++) {
+                capabilities.put(qName, atts.getQName(i), atts.getValue(i));
+            }
+        }
+
+        /**
+         * Returns the read capabilities.
+         * @return the read capabilities
+         */
+        public Capabilities getCapabilities() {
+            return capabilities;
+        }
+
+        /**
+         * Parses and returns capabilities from the given input source.
+         *
+         * @param inputSource The input source to read capabilities from
+         * @return the capabilities
+         * @throws SAXException if any SAX errors occur during processing
+         * @throws IOException if any I/O errors occur
+         * @throws ParserConfigurationException if a parser cannot be created
+         */
+        public static Capabilities parse(InputSource inputSource) throws SAXException, IOException, ParserConfigurationException {
+            CapabilitiesParser parser = new CapabilitiesParser();
+            SAXParserFactory.newInstance().newSAXParser().parse(inputSource, parser);
+            return parser.getCapabilities();
+        }
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/io/OsmApi.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 7472)
+++ /trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 7473)
@@ -27,5 +27,4 @@
 
 import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.openstreetmap.josm.Main;
@@ -37,12 +36,11 @@
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.Capabilities.CapabilitiesParser;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Utils;
 import org.openstreetmap.josm.tools.XmlParsingException;
-import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
-import org.xml.sax.helpers.DefaultHandler;
 
 /**
@@ -111,43 +109,21 @@
     }
 
-    /** the server URL */
+    /** Server URL */
     private String serverUrl;
 
-    /**
-     * Object describing current changeset
-     */
+    /** Object describing current changeset */
     private Changeset changeset;
 
-    /**
-     * API version used for server communications
-     */
+    /** API version used for server communications */
     private String version = null;
 
-    /** the api capabilities */
-    private Capabilities capabilities = new Capabilities();
-
-    /**
-     * true if successfully initialized
-     */
+    /** API capabilities */
+    private Capabilities capabilities = null;
+
+    /** true if successfully initialized */
     private boolean initialized = false;
 
     /**
-     * A parser for the "capabilities" response XML
-     */
-    private class CapabilitiesParser extends DefaultHandler {
-        @Override
-        public void startDocument() throws SAXException {
-            capabilities.clear();
-        }
-
-        @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
-            for (int i=0; i< atts.getLength(); i++) {
-                capabilities.put(qName, atts.getQName(i), atts.getValue(i));
-            }
-        }
-    }
-
-    /**
-     * creates an OSM api for a specific server URL
+     * Constructs a new {@code OsmApi} for a specific server URL.
      *
      * @param serverUrl the server URL. Must not be null
@@ -293,6 +269,5 @@
 
     private void initializeCapabilities(String xml) throws SAXException, IOException, ParserConfigurationException {
-        InputSource inputSource = new InputSource(new StringReader(xml));
-        SAXParserFactory.newInstance().newSAXParser().parse(inputSource, new CapabilitiesParser());
+        capabilities = CapabilitiesParser.parse(new InputSource(new StringReader(xml)));
     }
 
@@ -752,5 +727,5 @@
 
     /**
-     * Replies the API capabilities
+     * Replies the API capabilities.
      *
      * @return the API capabilities, or null, if the API is not initialized yet
Index: /trunk/src/org/openstreetmap/josm/tools/Utils.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 7472)
+++ /trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 7473)
@@ -653,4 +653,7 @@
             throw new IllegalArgumentException("Invalid HTTP url");
         }
+        if (Main.isDebugEnabled()) {
+            Main.debug("Opening HTTP connection to "+httpURL.toExternalForm());
+        }
         HttpURLConnection connection = (HttpURLConnection) httpURL.openConnection();
         connection.setRequestProperty("User-Agent", Version.getInstance().getFullAgentString());
