Index: trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTask.java	(revision 12678)
+++ trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadGpsTask.java	(revision 12679)
@@ -6,4 +6,5 @@
 import java.io.IOException;
 import java.net.URL;
+import java.util.Arrays;
 import java.util.Optional;
 import java.util.concurrent.Future;
@@ -31,4 +32,5 @@
 import org.openstreetmap.josm.io.BoundingBoxDownloader;
 import org.openstreetmap.josm.io.OsmServerLocationReader;
+import org.openstreetmap.josm.io.OsmServerLocationReader.GpxUrlPattern;
 import org.openstreetmap.josm.io.OsmServerReader;
 import org.openstreetmap.josm.io.OsmTransferException;
@@ -44,22 +46,9 @@
     private GpxLayer gpxLayer;
 
-    private static final String PATTERN_TRACE_ID = "https?://.*(osm|openstreetmap).org/trace/\\p{Digit}+/data";
-    private static final String PATTERN_USER_TRACE_ID = "https?://.*(osm|openstreetmap).org/user/[^/]+/traces/(\\p{Digit}+)";
-    private static final String PATTERN_EDIT_TRACE_ID = "https?://.*(osm|openstreetmap).org/edit/?\\?gpx=(\\p{Digit}+)(#.*)?";
-
-    private static final String PATTERN_TRACKPOINTS_BBOX = "https?://.*/api/0.6/trackpoints\\?bbox=.*,.*,.*,.*";
-
-    private static final String PATTERN_EXTERNAL_GPX_SCRIPT = "https?://.*exportgpx.*";
-    private static final String PATTERN_EXTERNAL_GPX_FILE = "https?://.*/(.*\\.gpx)";
-
     protected String newLayerName;
 
     @Override
     public String[] getPatterns() {
-        return new String[] {
-                PATTERN_EXTERNAL_GPX_FILE, PATTERN_EXTERNAL_GPX_SCRIPT,
-                PATTERN_TRACE_ID, PATTERN_USER_TRACE_ID, PATTERN_EDIT_TRACE_ID,
-                PATTERN_TRACKPOINTS_BBOX,
-        };
+        return Arrays.stream(GpxUrlPattern.values()).map(GpxUrlPattern::pattern).toArray(String[]::new);
     }
 
@@ -81,6 +70,6 @@
     public Future<?> loadUrl(boolean newLayer, String url, ProgressMonitor progressMonitor) {
         CheckParameterUtil.ensureParameterNotNull(url, "url");
-        final Optional<String> mappedUrl = Stream.of(PATTERN_USER_TRACE_ID, PATTERN_EDIT_TRACE_ID)
-                .map(p -> Pattern.compile(p).matcher(url))
+        final Optional<String> mappedUrl = Stream.of(GpxUrlPattern.USER_TRACE_ID, GpxUrlPattern.EDIT_TRACE_ID)
+                .map(p -> Pattern.compile(p.pattern()).matcher(url))
                 .filter(Matcher::matches)
                 .map(m -> "https://www.openstreetmap.org/trace/" + m.group(2) + "/data")
@@ -89,11 +78,10 @@
             return loadUrl(newLayer, mappedUrl.get(), progressMonitor);
         }
-        if (url.matches(PATTERN_TRACE_ID)
-         || url.matches(PATTERN_EXTERNAL_GPX_SCRIPT)
-         || url.matches(PATTERN_EXTERNAL_GPX_FILE)) {
+        if (Stream.of(GpxUrlPattern.TRACE_ID, GpxUrlPattern.EXTERNAL_GPX_SCRIPT, GpxUrlPattern.EXTERNAL_GPX_FILE)
+                .anyMatch(p -> url.matches(p.pattern()))) {
             downloadTask = new DownloadTask(newLayer,
                     new OsmServerLocationReader(url), progressMonitor);
             // Extract .gpx filename from URL to set the new layer name
-            Matcher matcher = Pattern.compile(PATTERN_EXTERNAL_GPX_FILE).matcher(url);
+            Matcher matcher = Pattern.compile(GpxUrlPattern.EXTERNAL_GPX_FILE.pattern()).matcher(url);
             newLayerName = matcher.matches() ? matcher.group(1) : null;
             // We need submit instead of execute so we can wait for it to finish and get the error
@@ -101,5 +89,5 @@
             return MainApplication.worker.submit(downloadTask);
 
-        } else if (url.matches(PATTERN_TRACKPOINTS_BBOX)) {
+        } else if (url.matches(GpxUrlPattern.TRACKPOINTS_BBOX.pattern())) {
             String[] table = url.split("\\?|=|&");
             for (int i = 0; i < table.length; i++) {
@@ -224,14 +212,3 @@
         return true;
     }
-
-    /**
-     * Determines if the given URL denotes an OSM gpx-related API call.
-     * @param url The url to check
-     * @return true if the url matches "Trace ID" API call or "Trackpoints bbox" API call, false otherwise
-     * @see GpxData#fromServer
-     * @since 5745
-     */
-    public static final boolean isFromServer(String url) {
-        return url != null && (url.matches(PATTERN_TRACE_ID) || url.matches(PATTERN_TRACKPOINTS_BBOX));
-    }
 }
Index: trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadNotesTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadNotesTask.java	(revision 12678)
+++ trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadNotesTask.java	(revision 12679)
@@ -7,4 +7,5 @@
 import java.io.IOException;
 import java.net.URL;
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.Future;
@@ -28,4 +29,5 @@
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.OsmServerLocationReader;
+import org.openstreetmap.josm.io.OsmServerLocationReader.NoteUrlPattern;
 import org.openstreetmap.josm.io.OsmServerReader;
 import org.openstreetmap.josm.io.OsmTransferException;
@@ -41,6 +43,4 @@
 public class DownloadNotesTask extends AbstractDownloadTask<NoteData> {
 
-    private static final String PATTERN_API_URL = "https?://.*/api/0.6/notes.*";
-    private static final String PATTERN_DUMP_FILE = "https?://.*/(.*\\.osn(.bz2)?)";
     /** Property defining the number of notes to be downloaded */
     public static final IntegerProperty DOWNLOAD_LIMIT = new IntegerProperty("osm.notes.downloadLimit", 1000);
@@ -98,5 +98,5 @@
     @Override
     public String[] getPatterns() {
-        return new String[] {PATTERN_API_URL, PATTERN_DUMP_FILE};
+        return Arrays.stream(NoteUrlPattern.values()).map(NoteUrlPattern::pattern).toArray(String[]::new);
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java	(revision 12678)
+++ trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java	(revision 12679)
@@ -7,4 +7,5 @@
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -35,4 +36,5 @@
 import org.openstreetmap.josm.io.BoundingBoxDownloader;
 import org.openstreetmap.josm.io.OsmServerLocationReader;
+import org.openstreetmap.josm.io.OsmServerLocationReader.OsmUrlPattern;
 import org.openstreetmap.josm.io.OsmServerReader;
 import org.openstreetmap.josm.io.OsmTransferCanceledException;
@@ -48,11 +50,4 @@
 public class DownloadOsmTask extends AbstractDownloadTask<DataSet> {
 
-    // CHECKSTYLE.OFF: SingleSpaceSeparator
-    protected static final String PATTERN_OSM_API_URL           = "https?://.*/api/0.6/(map|nodes?|ways?|relations?|\\*).*";
-    protected static final String PATTERN_OVERPASS_API_URL      = "https?://.*/interpreter\\?data=.*";
-    protected static final String PATTERN_OVERPASS_API_XAPI_URL = "https?://.*/xapi(\\?.*\\[@meta\\]|_meta\\?).*";
-    protected static final String PATTERN_EXTERNAL_OSM_FILE     = "https?://.*/.*\\.osm";
-    // CHECKSTYLE.ON: SingleSpaceSeparator
-
     protected Bounds currentBounds;
     protected DownloadTask downloadTask;
@@ -66,6 +61,5 @@
     public String[] getPatterns() {
         if (this.getClass() == DownloadOsmTask.class) {
-            return new String[]{PATTERN_OSM_API_URL, PATTERN_OVERPASS_API_URL,
-                PATTERN_OVERPASS_API_XAPI_URL, PATTERN_EXTERNAL_OSM_FILE};
+            return Arrays.stream(OsmUrlPattern.values()).map(OsmUrlPattern::pattern).toArray(String[]::new);
         } else {
             return super.getPatterns();
@@ -408,5 +402,5 @@
         if (url != null) {
             String urlString = url.toExternalForm();
-            if (urlString.matches(PATTERN_OSM_API_URL)) {
+            if (urlString.matches(OsmUrlPattern.OSM_API_URL.pattern())) {
                 // TODO: proper i18n after stabilization
                 Collection<String> items = new ArrayList<>();
Index: trunk/src/org/openstreetmap/josm/io/OsmServerLocationReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmServerLocationReader.java	(revision 12678)
+++ trunk/src/org/openstreetmap/josm/io/OsmServerLocationReader.java	(revision 12679)
@@ -9,5 +9,4 @@
 import java.util.List;
 
-import org.openstreetmap.josm.actions.downloadtasks.DownloadGpsTask;
 import org.openstreetmap.josm.data.gpx.GpxData;
 import org.openstreetmap.josm.data.notes.Note;
@@ -22,4 +21,87 @@
  */
 public class OsmServerLocationReader extends OsmServerReader {
+
+    // CHECKSTYLE.OFF: MethodParamPad
+    // CHECKSTYLE.OFF: SingleSpaceSeparator
+
+    /**
+     * Patterns for OSM data download URLs.
+     * @since 12679
+     */
+    public enum OsmUrlPattern {
+        OSM_API_URL           ("https?://.*/api/0.6/(map|nodes?|ways?|relations?|\\*).*"),
+        OVERPASS_API_URL      ("https?://.*/interpreter\\?data=.*"),
+        OVERPASS_API_XAPI_URL ("https?://.*/xapi(\\?.*\\[@meta\\]|_meta\\?).*"),
+        EXTERNAL_OSM_FILE     ("https?://.*/.*\\.osm");
+
+        private final String urlPattern;
+
+        OsmUrlPattern(String urlPattern) {
+            this.urlPattern = urlPattern;
+        }
+
+        /**
+         * Returns the URL pattern.
+         * @return the URL pattern
+         */
+        public String pattern() {
+            return urlPattern;
+        }
+    }
+
+    /**
+     * Patterns for GPX download URLs.
+     * @since 12679
+     */
+    public enum GpxUrlPattern {
+        TRACE_ID     ("https?://.*(osm|openstreetmap).org/trace/\\p{Digit}+/data"),
+        USER_TRACE_ID("https?://.*(osm|openstreetmap).org/user/[^/]+/traces/(\\p{Digit}+)"),
+        EDIT_TRACE_ID("https?://.*(osm|openstreetmap).org/edit/?\\?gpx=(\\p{Digit}+)(#.*)?"),
+
+        TRACKPOINTS_BBOX("https?://.*/api/0.6/trackpoints\\?bbox=.*,.*,.*,.*"),
+
+        EXTERNAL_GPX_SCRIPT("https?://.*exportgpx.*"),
+        EXTERNAL_GPX_FILE  ("https?://.*/(.*\\.gpx)");
+
+        private final String urlPattern;
+
+        GpxUrlPattern(String urlPattern) {
+            this.urlPattern = urlPattern;
+        }
+
+        /**
+         * Returns the URL pattern.
+         * @return the URL pattern
+         */
+        public String pattern() {
+            return urlPattern;
+        }
+    }
+
+    /**
+     * Patterns for Note download URLs.
+     * @since 12679
+     */
+    public enum NoteUrlPattern {
+        API_URL  ("https?://.*/api/0.6/notes.*"),
+        DUMP_FILE("https?://.*/(.*\\.osn(.bz2)?)");
+
+        private final String urlPattern;
+
+        NoteUrlPattern(String urlPattern) {
+            this.urlPattern = urlPattern;
+        }
+
+        /**
+         * Returns the URL pattern.
+         * @return the URL pattern
+         */
+        public String pattern() {
+            return urlPattern;
+        }
+    }
+
+    // CHECKSTYLE.ON: SingleSpaceSeparator
+    // CHECKSTYLE.ON: MethodParamPad
 
     protected final String url;
@@ -163,5 +245,5 @@
             gpxParsedProperly = reader.parse(false);
             GpxData result = reader.getGpxData();
-            result.fromServer = DownloadGpsTask.isFromServer(url);
+            result.fromServer = isGpxFromServer(url);
             return result;
         }
@@ -185,3 +267,14 @@
         }
     }
+
+    /**
+     * Determines if the given URL denotes an OSM gpx-related API call.
+     * @param url The url to check
+     * @return true if the url matches "Trace ID" API call or "Trackpoints bbox" API call, false otherwise
+     * @see GpxData#fromServer
+     * @since 12679
+     */
+    public static final boolean isGpxFromServer(String url) {
+        return url != null && (url.matches(GpxUrlPattern.TRACE_ID.pattern()) || url.matches(GpxUrlPattern.TRACKPOINTS_BBOX.pattern()));
+    }
 }
