Index: trunk/scripts/taginfoextract.groovy
===================================================================
--- trunk/scripts/taginfoextract.groovy	(revision 8680)
+++ trunk/scripts/taginfoextract.groovy	(revision 8681)
@@ -7,14 +7,7 @@
  * groovy -cp dist/josm-custom.jar scripts/taginfoextract.groovy -t mappaint
  * groovy -cp dist/josm-custom.jar scripts/taginfoextract.groovy -t presets
+ * groovy -cp dist/josm-custom.jar scripts/taginfoextract.groovy -t external_presets
  */
 import groovy.json.JsonBuilder
-
-import java.awt.image.BufferedImage
-import java.nio.file.FileSystems
-import java.nio.file.Files
-import java.nio.file.Path
-
-import javax.imageio.ImageIO
-
 import org.openstreetmap.josm.Main
 import org.openstreetmap.josm.data.Version
@@ -29,10 +22,11 @@
 import org.openstreetmap.josm.gui.mappaint.Environment
 import org.openstreetmap.josm.gui.mappaint.LineElemStyle
+import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference
 import org.openstreetmap.josm.gui.mappaint.MultiCascade
-import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference
+import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.SimpleKeyValueCondition
 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource
-import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.SimpleKeyValueCondition
 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector
 import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser
+import org.openstreetmap.josm.gui.preferences.map.TaggingPresetPreference
 import org.openstreetmap.josm.gui.tagging.TaggingPreset
 import org.openstreetmap.josm.gui.tagging.TaggingPresetItems
@@ -41,4 +35,10 @@
 import org.openstreetmap.josm.io.CachedFile
 import org.openstreetmap.josm.tools.Utils
+
+import javax.imageio.ImageIO
+import java.awt.image.BufferedImage
+import java.nio.file.FileSystems
+import java.nio.file.Files
+import java.nio.file.Path
 
 class taginfoextract {
@@ -187,4 +187,6 @@
         } else if (options.t == 'presets') {
             script.run_presets()
+        } else if (options.t == 'external_presets') {
+            script.run_external_presets()
         } else {
             System.err.println 'Invalid type ' + options.t
@@ -235,6 +237,11 @@
     void run_presets() {
         init()
+        def presets = TaggingPresetReader.readAll(input_file, true)
+        def tags = convert_presets(presets. "", true)
+        write_json("JOSM main presets", "Tags supported by the default presets in the OSM editor JOSM", tags)
+    }
+
+    def convert_presets(Iterable<TaggingPreset> presets, String descriptionPrefix, boolean addImages) {
         def tags = []
-        def presets = TaggingPresetReader.readAll(input_file, true)
         for (TaggingPreset preset : presets) {
             for (TaggingPresetItems.KeyedItem item : Utils.filteredCollection(preset.data, TaggingPresetItems.KeyedItem.class)) {
@@ -247,16 +254,38 @@
                 for (String value : values) {
                     def tag = [
-                            description: preset.name,
+                            description: descriptionPrefix + preset.name,
                             key: item.key,
                             value: value,
                             object_types: preset.types.collect {it == TaggingPresetType.CLOSEDWAY ? "area" : it.toString().toLowerCase()},
                     ]
-                    if (preset.iconName) tag += [icon_url: find_image_url(preset.iconName)]
+                    if (addImages && preset.iconName) tag += [icon_url: find_image_url(preset.iconName)]
                     tags += tag
                 }
             }
         }
-
-        write_json("JOSM main presets", "Tags supported by the default presets in the OSM editor JOSM", tags)
+        return tags
+    }
+
+    void run_external_presets() {
+        init()
+        def sources = new TaggingPresetPreference.TaggingPresetSourceEditor().loadAndGetAvailableSources()
+        def tags = []
+        for (def source : sources) {
+            if (source.url.startsWith("resource")) {
+                // default presets
+                continue;
+            }
+            try {
+                println "Loading ${source.url}"
+                def presets = TaggingPresetReader.readAll(source.url, false)
+                def t = convert_presets(presets, source.title + " ", false)
+                println "Converting ${t.size()} presets of ${source.title}"
+                tags += t
+            } catch (Exception ex) {
+                System.err.println("Skipping ${source.url} due to error")
+                ex.printStackTrace()
+            }
+        }
+        write_json("JOSM user presets", "Tags supported by the user contributed presets in the OSM editor JOSM", tags)
     }
 
@@ -325,4 +354,5 @@
     def init() {
         Main.initApplicationPreferences()
+        Main.determinePlatformHook()
         Main.pref.enableSaveOnPut(false)
         Main.setProjection(Projections.getProjectionByCode("EPSG:3857"))
Index: trunk/src/org/openstreetmap/josm/gui/preferences/SourceEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/SourceEditor.java	(revision 8680)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/SourceEditor.java	(revision 8681)
@@ -443,4 +443,17 @@
     public Collection<SourceEntry> getActiveSources() {
         return activeSourcesModel.getSources();
+    }
+
+    /**
+     * Synchronously loads available sources and returns the parsed list.
+     */
+    Collection<ExtendedSourceEntry> loadAndGetAvailableSources() {
+        try {
+            final SourceLoader loader = new SourceLoader(availableSourcesUrl, sourceProviders);
+            loader.realRun();
+            return loader.sources;
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
     }
 
