Index: applications/editors/josm/plugins/roadsigns/src/org/openstreetmap/josm/plugins/roadsigns/RoadSignsPlugin.java
===================================================================
--- applications/editors/josm/plugins/roadsigns/src/org/openstreetmap/josm/plugins/roadsigns/RoadSignsPlugin.java	(revision 35935)
+++ applications/editors/josm/plugins/roadsigns/src/org/openstreetmap/josm/plugins/roadsigns/RoadSignsPlugin.java	(revision 36316)
@@ -2,4 +2,5 @@
 package org.openstreetmap.josm.plugins.roadsigns;
 
+import static org.openstreetmap.josm.tools.I18n.marktr;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
@@ -9,9 +10,9 @@
 import java.awt.event.KeyEvent;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -37,44 +38,64 @@
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Shortcut;
-import org.openstreetmap.josm.tools.Utils;
 import org.xml.sax.SAXException;
 
+/**
+ * The entry point for the {@link RoadSignsPlugin}
+ */
 public class RoadSignsPlugin extends Plugin {
+    private static final String SELECTION_PREFERENCE = "plugin.roadsigns.preset.selection";
+    private static final String SOURCES_PREFERENCE = "plugin.roadsigns.sources";
+    private static final String LAST_SOURCES_PREFERENCE = "plugin.roadsigns.sources.last";
+    private static final String CUSTOM = marktr("custom");
     static PresetMetaData selectedPreset;
-    public static List<Sign> signs;
-    public static List<String> iconDirs;
-
-    public static RoadSignsPlugin plugin;
-
-    public static final PresetMetaData PRESET_BE = new PresetMetaData(
+    static List<Sign> signs;
+    static List<String> iconDirs;
+
+    private static RoadSignsPlugin plugin;
+    
+    private static final PresetMetaData PRESET_AT = new PresetMetaData(
+            "AT", tr("Austria"), "resource://data/roadsignpresetAT.xml", "resource://images/AT/");
+    private static final PresetMetaData PRESET_BE = new PresetMetaData(
             "BE", tr("Belgium"), "resource://data/roadsignpresetBE.xml", "resource://images/BE/");
-    public static final PresetMetaData PRESET_CZ = new PresetMetaData(
+    private static final PresetMetaData PRESET_CZ = new PresetMetaData(
             "CZ", tr("Czech Republic"), "resource://data/roadsignpresetCZ.xml", "resource://images/CZ/");
-    public static final PresetMetaData PRESET_ES = new PresetMetaData(
+    private static final PresetMetaData PRESET_ES = new PresetMetaData(
             "ES", tr("Spain"), "resource://data/roadsignpresetES.xml", "resource://images/ES/");
-    public static final PresetMetaData PRESET_DE = new PresetMetaData(
+    private static final PresetMetaData PRESET_DE = new PresetMetaData(
             "DE", tr("Germany"), "resource://data/roadsignpresetDE.xml", "resource://images/DE/");
-    public static final PresetMetaData PRESET_PL = new PresetMetaData(
+    private static final PresetMetaData PRESET_PL = new PresetMetaData(
             "PL", tr("Poland"), "resource://data/roadsignpresetPL.xml", "resource://images/PL/");
-    public static final PresetMetaData PRESET_SK = new PresetMetaData(
+    private static final PresetMetaData PRESET_SK = new PresetMetaData(
             "SK", tr("Slovakia"), "resource://data/roadsignpresetSK.xml", "resource://images/SK/");
-    public static final Collection<PresetMetaData> DEFAULT_PRESETS = Arrays.asList(
-            PRESET_BE, PRESET_CZ, PRESET_ES, PRESET_DE, PRESET_PL, PRESET_SK);
-
+    private static final Collection<PresetMetaData> DEFAULT_PRESETS = Arrays.asList(
+            PRESET_AT, PRESET_BE, PRESET_CZ, PRESET_ES, PRESET_DE, PRESET_PL, PRESET_SK);
+
+    private static void setPluginInstance(RoadSignsPlugin plugin) {
+        RoadSignsPlugin.plugin = plugin;
+    }
+
+    /**
+     * Create a new plugin instance
+     * @param info The info to use when creating this instance
+     */
     public RoadSignsPlugin(PluginInformation info) {
         super(info);
-        plugin = this;
+        setPluginInstance(this);
         registerAction();
     }
 
-    public static File pluginDir() {
+    /**
+     * Get the plugin directory
+     * @return The plugin directory
+     */
+    static File pluginDir() {
         File dir = plugin.getPluginDirs().getUserDataDirectory(false);
-        if (!dir.exists()) {
-            dir.mkdirs();
+        if (!dir.exists() && !dir.mkdirs()) {
+            throw new UncheckedIOException(new IOException("Could not create directory: " + dir.getAbsolutePath()));
         }
         return dir;
     }
 
-    private void registerAction() {
+    private static void registerAction() {
         JButton btn = new JButton(new RoadSignAction());
         btn.setText(null);
@@ -95,5 +116,5 @@
         @Override
         public void actionPerformed(ActionEvent e) {
-            String code = Config.getPref().get("plugin.roadsigns.preset.selection", null);
+            String code = Config.getPref().get(SELECTION_PREFERENCE, null);
             if (code == null) {
                 ExtendedDialog ed = new ExtendedDialog(MainApplication.getMainFrame(), tr("Settings"), tr("Ok"), tr("Cancel"));
@@ -106,4 +127,5 @@
                     settings.apply();
                 } catch (IOException ex) {
+                    Logging.trace(ex);
                     return;
                 }
@@ -112,4 +134,5 @@
                 loadSignPreset();
             } catch (IOException ex) {
+                Logging.trace(ex);
                 return;
             }
@@ -120,8 +143,15 @@
     }
 
+    /**
+     * A struct class for storing metadata
+     */
     public static class PresetMetaData {
+        /** The country code */
         @StructEntry public String code;
+        /** The display name */
         @StructEntry public String display_name;
+        /** The path to the preset */
         @StructEntry public String preset_path;
+        /** The path to the icons */
         @StructEntry public String icon_path;
 
@@ -129,9 +159,16 @@
         }
 
-        public PresetMetaData(String country_code, String display_name, String preset_path, String icons_path) {
-            this.code = country_code;
-            this.display_name = display_name;
-            this.preset_path = preset_path;
-            this.icon_path = icons_path;
+        /**
+         * Create a new record with the specified data
+         * @param countryCode The country code to use
+         * @param displayName The display name
+         * @param presetPath The path to the preset
+         * @param iconsPath The path to the icons
+         */
+        public PresetMetaData(String countryCode, String displayName, String presetPath, String iconsPath) {
+            this.code = countryCode;
+            this.display_name = displayName;
+            this.preset_path = presetPath;
+            this.icon_path = iconsPath;
         }
 
@@ -143,17 +180,16 @@
 
     public static void setSelectedPreset(PresetMetaData preset) throws IOException {
-        Config.getPref().put("plugin.roadsigns.preset.selection", preset.code);
+        Config.getPref().put(SELECTION_PREFERENCE, preset.code);
         loadSignPreset();
     }
 
     public static List<PresetMetaData> getAvailablePresetsMetaData() {
-
-        List<PresetMetaData> presetsData = StructUtils.getListOfStructs(
-                Config.getPref(), "plugin.roadsigns.presets", DEFAULT_PRESETS, PresetMetaData.class);
-
-        String customFile = Config.getPref().get("plugin.roadsigns.sources", null);
+        List<PresetMetaData> presetsData = Objects.requireNonNull(StructUtils.getListOfStructs(
+                Config.getPref(), "plugin.roadsigns.presets", DEFAULT_PRESETS, PresetMetaData.class));
+
+        String customFile = Config.getPref().get(SOURCES_PREFERENCE, null);
         if (customFile == null) {
             // for legacy reasons, try both string and collection preference type
-            List<String> customFiles = Config.getPref().getList("plugin.roadsigns.sources", null);
+            List<String> customFiles = Config.getPref().getList(SOURCES_PREFERENCE, null);
             if (customFiles != null && !customFiles.isEmpty()) {
                 customFile = customFiles.iterator().next();
@@ -162,53 +198,62 @@
 
         if (customFile != null) {
-            // first check, if custom file preference has changed. If yes,
-            // change the current preset selection to custom directly
-            String lastCustomFile = Config.getPref().get("plugin.roadsigns.sources.last", null);
-            if (!Objects.equals(customFile, lastCustomFile)) {
-                Config.getPref().put("plugin.roadsigns.sources.last", customFile);
-                Config.getPref().put("plugin.roadsigns.preset.selection", "custom");
-            }
-
-            String customIconDirsStr = Config.getPref().get("plugin.roadsigns.icon.sources", null);
-            List<String> customIconDirs = null;
-            if (customIconDirsStr != null) {
-                customIconDirs = new ArrayList<>(Arrays.asList(customIconDirsStr.split(",")));
-            } else {
-                customIconDirs = Config.getPref().getList("plugin.roadsigns.icon.sources", null);
-            }
-            if (customIconDirs != null) {
-                customIconDirs = new ArrayList<>(customIconDirs);
-            } else {
-                customIconDirs = new ArrayList<>();
-            }
-            // add icon directory relative to preset file
-            if (!customFile.startsWith("resource:")) {
-                String parentDir = null;
-                try {
-                    URL url = new URL(customFile);
-                    parentDir = url.getPath();
-                } catch (MalformedURLException ex) {
-                    File f = new File(customFile);
-                    parentDir = f.getParent();
-                }
-                if (parentDir != null && !parentDir.isEmpty()) {
-                    customIconDirs.add(parentDir);
-                }
-            }
-            if (Config.getPref().getBoolean("plugin.roadsigns.use_default_icon_source", true)) {
-                customIconDirs.add("resource://images/");
-            }
-            presetsData.add(new PresetMetaData("custom", tr("custom"), customFile,
-                    String.join(",", customIconDirs)));
+            presetsData.add(readCustomFile(customFile));
         } else {
-            Config.getPref().put("plugin.roadsigns.sources.last", null);
+            Config.getPref().put(LAST_SOURCES_PREFERENCE, null);
         }
 
         return presetsData;
+    }
+
+    /**
+     * Read the custom preset file
+     * @param customFile The file to read
+     * @return The metadata for that custom file
+     */
+    private static PresetMetaData readCustomFile(String customFile) {
+        // first check, if custom file preference has changed. If yes,
+        // change the current preset selection to custom directly
+        String lastCustomFile = Config.getPref().get(LAST_SOURCES_PREFERENCE, null);
+        if (!Objects.equals(customFile, lastCustomFile)) {
+            Config.getPref().put(LAST_SOURCES_PREFERENCE, customFile);
+            Config.getPref().put(SELECTION_PREFERENCE, CUSTOM);
+        }
+
+        String customIconDirsStr = Config.getPref().get("plugin.roadsigns.icon.sources", null);
+        List<String> customIconDirs = null;
+        if (customIconDirsStr != null) {
+            customIconDirs = new ArrayList<>(Arrays.asList(customIconDirsStr.split(",")));
+        } else {
+            customIconDirs = Config.getPref().getList("plugin.roadsigns.icon.sources", null);
+        }
+        if (customIconDirs != null) {
+            customIconDirs = new ArrayList<>(customIconDirs);
+        } else {
+            customIconDirs = new ArrayList<>();
+        }
+        // add icon directory relative to preset file
+        if (!customFile.startsWith("resource:")) {
+            String parentDir;
+            try {
+                parentDir = new URI(customFile).getPath();
+            } catch (URISyntaxException ex) {
+                Logging.trace(ex);
+                File f = new File(customFile);
+                parentDir = f.getParent();
+            }
+            if (parentDir != null && !parentDir.isEmpty()) {
+                customIconDirs.add(parentDir);
+            }
+        }
+        if (Config.getPref().getBoolean("plugin.roadsigns.use_default_icon_source", true)) {
+            customIconDirs.add("resource://images/");
+        }
+        return new PresetMetaData(CUSTOM, tr(CUSTOM), customFile,
+                String.join(",", customIconDirs));
     }
 
     protected static void loadSignPreset() throws IOException {
         List<PresetMetaData> presetsData = getAvailablePresetsMetaData();
-        String code = Config.getPref().get("plugin.roadsigns.preset.selection", null);
+        String code = Config.getPref().get(SELECTION_PREFERENCE, null);
 
         for (PresetMetaData data : presetsData) {
@@ -228,9 +273,8 @@
         String source = selectedPreset.preset_path;
 
-        try {
-            InputStream in = getInputStream(source);
+        try (CachedFile cachedFile = new CachedFile(source);
+            InputStream in = cachedFile.getInputStream()) {
             RoadSignsReader reader = new RoadSignsReader(in);
             signs = reader.parse();
-
         } catch (IOException ex) {
             Logging.error(ex);
@@ -253,21 +297,3 @@
         }
     }
-
-    /**
-     * Returns an inputstream from urls, files and classloaders, depending on the name.
-     */
-    @SuppressWarnings("resource")
-    public static InputStream getInputStream(String source) throws IOException {
-        InputStream in = null;
-        if (source.startsWith("http://") || source.startsWith("https://") || source.startsWith("ftp://")) {
-            in = new CachedFile(source).getInputStream();
-        } else if (source.startsWith("file:")) {
-            in = new URL(source).openStream();
-        } else if (source.startsWith("resource://")) {
-            in = RoadSignsPlugin.class.getResourceAsStream(source.substring("resource:/".length()));
-        } else {
-            in = new FileInputStream(source);
-        }
-        return in;
-    }
 }
