Index: src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java
===================================================================
--- src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java	(revision 1859)
+++ src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java	(working copy)
@@ -11,6 +11,8 @@
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.io.OsmConnection;
+import org.openstreetmap.josm.io.CredentialsManager.PreferenceAdditions;
 
 public class ServerAccessPreference implements PreferenceSetting {
 
@@ -25,41 +27,22 @@
      */
     private JTextField osmDataServer = new JTextField(20);
     /**
-     * Editfield for the username to the OSM account.
+     * Provide username and password input editfields.
+     * Store the values if user hits OK.
      */
-    private JTextField osmDataUsername = new JTextField(20);
-    /**
-     * Passwordfield for the userpassword of the REST API.
-     */
-    private JPasswordField osmDataPassword = new JPasswordField(20);
+    private PreferenceAdditions credentialsPA = OsmConnection.credentialsManager.newPreferenceAdditions();
 
     public void addGui(PreferenceDialog gui) {
         osmDataServer.setText(Main.pref.get("osm-server.url", "http://api.openstreetmap.org/api"));
-        osmDataUsername.setText(Main.pref.get("osm-server.username"));
-        osmDataPassword.setText(Main.pref.get("osm-server.password"));
-
         osmDataServer.setToolTipText(tr("The base URL for the OSM server (REST API)"));
-        osmDataUsername.setToolTipText(tr("Login name (e-mail) to the OSM account."));
-        osmDataPassword.setToolTipText(tr("Login password to the OSM account. Leave blank to not store any password."));
-
         gui.connection.add(new JLabel(tr("Base Server URL")), GBC.std());
         gui.connection.add(osmDataServer, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-        gui.connection.add(new JLabel(tr("OSM username (e-mail)")), GBC.std());
-        gui.connection.add(osmDataUsername, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-        gui.connection.add(new JLabel(tr("OSM password")), GBC.std());
-        gui.connection.add(osmDataPassword, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,0));
-        JLabel warning = new JLabel(tr("<html>" +
-                "WARNING: The password is stored in plain text in the preferences file.<br>" +
-                "The password is transferred in plain text to the server, encoded in the URL.<br>" +
-        "<b>Do not use a valuable Password.</b></html>"));
-        warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
-        gui.connection.add(warning, GBC.eop().fill(GBC.HORIZONTAL));
+        credentialsPA.addPreferenceOptions(gui.connection);
     }
 
     public boolean ok() {
         Main.pref.put("osm-server.url", osmDataServer.getText());
-        Main.pref.put("osm-server.username", osmDataUsername.getText());
-        Main.pref.put("osm-server.password", String.valueOf(osmDataPassword.getPassword()));
+        credentialsPA.preferencesChanged();
         return false;
     }
 }
Index: src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java	(revision 1859)
+++ src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java	(working copy)
@@ -39,7 +39,7 @@
 
     // some common tabs
     public final JPanel display = createPreferenceTab("display", tr("Display Settings"), tr("Various settings that influence the visual representation of the whole program."));
-    public final JPanel connection = createPreferenceTab("connection", I18n.tr("Connection Settings"), I18n.tr("Connection Settings for the OSM server."));
+    public final JPanel connection = createPreferenceTab("connection", I18n.tr("Connection Settings"), I18n.tr("Connection Settings for the OSM server."),true);
     public final JPanel map = createPreferenceTab("map", I18n.tr("Map Settings"), I18n.tr("Settings for the map projection and data interpretation."));
     public final JPanel audio = createPreferenceTab("audio", I18n.tr("Audio Settings"), I18n.tr("Settings for the audio player and audio markers."));
 
Index: src/org/openstreetmap/josm/io/CredentialsManager.java
===================================================================
--- src/org/openstreetmap/josm/io/CredentialsManager.java	(revision 0)
+++ src/org/openstreetmap/josm/io/CredentialsManager.java	(revision 0)
@@ -0,0 +1,54 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import org.openstreetmap.josm.io.OsmConnection.OsmAuth;
+
+/**
+ * Manages how username and password are stored. In addition all 
+ * username/password-related user interaction is encapsulated here.
+ */
+public interface CredentialsManager {
+    /**
+     * lookupUsername, lookupPassword:
+     *
+     * Should throw or return non-null, possibly empty String.
+     */
+    public String lookupUsername() throws CMException;
+    public String lookupPassword() throws CMException;
+
+    /**
+     * storeUsername, storePassword:
+     *
+     * May silently fail to store.
+     */
+    public void storeUsername(String username) throws CMException;
+    public void storePassword(String password) throws CMException;
+
+    /**
+     * If authentication using the stored credentials fails, this method is
+     * called to promt for new username/password.
+     */
+    public java.net.PasswordAuthentication getPasswordAuthentication(OsmAuth caller);
+
+    /**
+     * Credentials-related preference gui.
+     */
+    public interface PreferenceAdditions {
+        public void addPreferenceOptions(javax.swing.JPanel panel);
+        public void preferencesChanged();
+    }
+    public PreferenceAdditions newPreferenceAdditions();
+
+    public class CMException extends Exception {
+        public CMException() {super();}
+        public CMException(String message, Throwable cause) {super(message, cause);}
+        public CMException(String message) {super(message);}
+        public CMException(Throwable cause) {super(cause);}
+    }
+    public class NoContentException extends CMException {
+        public NoContentException() {super();}
+        public NoContentException(String message, Throwable cause) {super(message, cause);}
+        public NoContentException(String message) {super(message);}
+        public NoContentException(Throwable cause) {super(cause);}
+    }
+}
Index: src/org/openstreetmap/josm/io/OsmConnection.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmConnection.java	(revision 1859)
+++ src/org/openstreetmap/josm/io/OsmConnection.java	(working copy)
@@ -24,6 +24,7 @@
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.tools.Base64;
 import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.io.CredentialsManager.CMException;
 
 /**
  * Base class that handles common things like authentication for the reader and writer
@@ -35,8 +36,17 @@
 
     protected boolean cancel = false;
     protected HttpURLConnection activeConnection;
+    /**
+     * Handles password storage and some related gui-components.
+     * It can be set by a plugin. This may happen at startup and
+     * by changing the preferences.
+     * Syncronize on this object to get or set a consistent
+     * username/password pair.
+     */
+    public static CredentialsManager credentialsManager = new PlainCredentialsManager();
 
     private static OsmAuth authentication = new OsmAuth();
+
     /**
      * Initialize the http defaults and the authenticator.
      */
@@ -54,20 +64,93 @@
     /**
      * The authentication class handling the login requests.
      */
-    private static class OsmAuth extends Authenticator {
+    public static class OsmAuth extends Authenticator {
         /**
          * Set to true, when the autenticator tried the password once.
          */
-        boolean passwordtried = false;
+        public boolean passwordtried = false;
         /**
          * Whether the user cancelled the password dialog
          */
-        boolean authCancelled = false;
+        public boolean authCancelled = false;
+        @Override protected PasswordAuthentication getPasswordAuthentication() {
+            return credentialsManager.getPasswordAuthentication(this);
+        }
+    }
 
-        @Override protected PasswordAuthentication getPasswordAuthentication() {
-            String username = Main.pref.get("osm-server.username");
+    /**
+     * Must be called before each connection attemp to initialize the authentication.
+     */
+    protected final void initAuthentication() {
+        authentication.authCancelled = false;
+        authentication.passwordtried = false;
+    }
+
+    /**
+     * @return Whether the connection was cancelled.
+     */
+    protected final boolean isAuthCancelled() {
+        return authentication.authCancelled;
+    }
+
+    public void cancel() {
+        //TODO
+        //Main.pleaseWaitDlg.currentAction.setText(tr("Aborting..."));
+        cancel = true;
+        if (activeConnection != null) {
+            activeConnection.setConnectTimeout(100);
+            activeConnection.setReadTimeout(100);
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException ex) {}
+            activeConnection.disconnect();
+        }
+    }
+
+    protected void addAuth(HttpURLConnection con) throws CharacterCodingException {
+        CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
+        String auth;
+        try {
+            synchronized (credentialsManager) {
+                auth = credentialsManager.lookupUsername() + ":" + credentialsManager.lookupPassword();
+            }
+        } catch (CMException e) {
+            auth = ":";
+        }
+        ByteBuffer bytes = encoder.encode(CharBuffer.wrap(auth));
+        con.addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));
+    }
+
+    public static class PlainCredentialsManager implements CredentialsManager {
+        public String lookupUsername() throws CMException {
+            String username = Main.pref.get("osm-server.username", null);
+            if (username == null) throw new CredentialsManager.NoContentException();
+            return username;
+        }
+        public String lookupPassword() throws CMException {
             String password = Main.pref.get("osm-server.password");
-            if (passwordtried || username.equals("") || password.equals("")) {
+            if (password == null) throw new CredentialsManager.NoContentException();
+            return password;
+        }
+        public void storeUsername(String username) {
+            Main.pref.put("osm-server.username", username);
+        }
+        public void storePassword(String password) {
+            Main.pref.put("osm-server.password", password);
+        }
+        public PasswordAuthentication getPasswordAuthentication(OsmAuth caller) {
+            String username, password;
+            try {
+                username = lookupUsername();
+            } catch (CMException e) {
+                username = "";
+            }
+            try {
+                password = lookupPassword();
+            } catch (CMException e) {
+                password = "";
+            }
+            if (caller.passwordtried || username.equals("") || password.equals("")) {
                 JPanel p = new JPanel(new GridBagLayout());
                 if (!username.equals("") && !password.equals("")) {
                     p.add(new JLabel(tr("Incorrect password or username.")), GBC.eop());
@@ -92,56 +175,71 @@
                         new String[] {"ok.png", "cancel.png"}).getValue();
 
                 if (choice != 1) {
-                    authCancelled = true;
+                    caller.authCancelled = true;
                     return null;
                 }
                 username = usernameField.getText();
                 password = String.valueOf(passwordField.getPassword());
                 if (savePassword.isSelected()) {
-                    Main.pref.put("osm-server.username", username);
-                    Main.pref.put("osm-server.password", password);
+                    storeUsername(username);
+                    storePassword(password);
                 }
                 if (username.equals(""))
                     return null;
             }
-            passwordtried = true;
+            caller.passwordtried = true;
             return new PasswordAuthentication(username, password.toCharArray());
         }
-    }
+        public PreferenceAdditions newPreferenceAdditions() {
+            return new PreferenceAdditions() {
+                /**
+                 * Editfield for the username to the OSM account.
+                 */
+                private JTextField osmDataUsername = new JTextField(20);
+                /**
+                 * Passwordfield for the userpassword of the REST API.
+                 */
+                private JPasswordField osmDataPassword = new JPasswordField(20);
 
-    /**
-     * Must be called before each connection attemp to initialize the authentication.
-     */
-    protected final void initAuthentication() {
-        authentication.authCancelled = false;
-        authentication.passwordtried = false;
-    }
+                private String oldUsername = "";
+                private String oldPassword = "";
 
-    /**
-     * @return Whether the connection was cancelled.
-     */
-    protected final boolean isAuthCancelled() {
-        return authentication.authCancelled;
-    }
-
-    public void cancel() {
-        //TODO
-        //Main.pleaseWaitDlg.currentAction.setText(tr("Aborting..."));
-        cancel = true;
-        if (activeConnection != null) {
-            activeConnection.setConnectTimeout(100);
-            activeConnection.setReadTimeout(100);
-            try {
-                Thread.sleep(100);
-            } catch (InterruptedException ex) {}
-            activeConnection.disconnect();
+                public void addPreferenceOptions(JPanel panel) {
+                    try {
+                        oldUsername = lookupUsername();
+                    } catch (CMException e) {
+                        oldUsername = "";
+                    }
+                    try {
+                        oldPassword = lookupPassword();
+                    } catch (CMException e) {
+                        oldPassword = "";
+                    }
+                    osmDataUsername.setText(oldUsername);
+                    osmDataPassword.setText(oldPassword);
+                    osmDataUsername.setToolTipText(tr("Login name (e-mail) to the OSM account."));
+                    osmDataPassword.setToolTipText(tr("Login password to the OSM account. Leave blank to not store any password."));
+                    panel.add(new JLabel(tr("OSM username (e-mail)")), GBC.std());
+                    panel.add(osmDataUsername, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
+                    panel.add(new JLabel(tr("OSM password")), GBC.std());
+                    panel.add(osmDataPassword, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,0));
+                    JLabel warning = new JLabel(tr("<html>" +
+                            "WARNING: The password is stored in plain text in the preferences file.<br>" +
+                            "The password is transferred in plain text to the server, encoded in the URL.<br>" +
+                            "<b>Do not use a valuable Password.</b></html>"));
+                    warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
+                    panel.add(warning, GBC.eop().fill(GBC.HORIZONTAL));
+                }
+                public void preferencesChanged() {
+                    String newUsername = osmDataUsername.getText();
+                    String newPassword = String.valueOf(osmDataPassword.getPassword());
+                    if (!oldUsername.equals(newUsername))
+                        storeUsername(newUsername);
+                    if (!oldPassword.equals(newPassword))
+                        storePassword(newPassword);
+                }
+            };
         }
     }
+}
 
-    protected void addAuth(HttpURLConnection con) throws CharacterCodingException {
-        CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
-        String auth = Main.pref.get("osm-server.username") + ":" + Main.pref.get("osm-server.password");
-        ByteBuffer bytes = encoder.encode(CharBuffer.wrap(auth));
-        con.addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));
-    }
-}
