Index: /trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java	(revision 4245)
+++ /trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java	(revision 4246)
@@ -53,4 +53,18 @@
  * So for getValue(), setDefaultButton(int) and setCancelButton(int) the
  * first button has index 1.
+ * 
+ * Simple example:
+ * <code>
+ *  ExtendedDialog ed = new ExtendedDialog(
+ *          Main.parent, tr("Dialog Title"),
+ *          new String[] {tr("Ok"), tr("Cancel")});
+ *  ed.setButtonIcons(new String[] {"ok", "cancel"});   // optional
+ *  ed.setIcon(JOptionPane.WARNING_MESSAGE);            // optional
+ *  ed.setContent(tr("Really proceed? Interesting things may happen..."));
+ *  ed.showDialog();
+ *  if (ed.getValue() == 1) { // user clicked first button "Ok"
+ *      // proceed...
+ *  }
+ * </code>
  */
 public class ExtendedDialog extends JDialog {
@@ -282,8 +296,8 @@
         JPanel buttonsPanel = new JPanel(new GridBagLayout());
 
-        for(int i=0; i < bTexts.length; i++) {
+        for (int i=0; i < bTexts.length; i++) {
             final int final_i = i;
             Action action = new AbstractAction(bTexts[i]) {
-                public void actionPerformed(ActionEvent evt) {
+                @Override public void actionPerformed(ActionEvent evt) {
                     buttonAction(final_i, evt);
                 }
@@ -415,5 +429,5 @@
     private void setupEscListener() {
         Action actionListener = new AbstractAction() {
-            public void actionPerformed(ActionEvent actionEvent) {
+            @Override public void actionPerformed(ActionEvent actionEvent) {
                 // 0 means that the dialog has been closed otherwise.
                 // We need to set it to zero again, in case the dialog has been re-used
@@ -535,5 +549,5 @@
         if (toggleable && defaultButton != null) {
             SwingUtilities.invokeLater(new Runnable() {
-                public void run() {
+                @Override public void run() {
                     defaultButton.requestFocusInWindow();
                 }
@@ -611,5 +625,5 @@
         }
 
-        public void actionPerformed(ActionEvent e) {
+        @Override public void actionPerformed(ActionEvent e) {
             HelpBrowser.setUrlForHelpTopic(helpTopic);
         }
Index: /trunk/src/org/openstreetmap/josm/gui/JosmUserIdentityManager.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/JosmUserIdentityManager.java	(revision 4245)
+++ /trunk/src/org/openstreetmap/josm/gui/JosmUserIdentityManager.java	(revision 4246)
@@ -25,5 +25,5 @@
  *
  * The current user is fully identified if JOSM knows both the user name and the unique
- * id of the users OSM account. The later is retrieved from the OSM server with a
+ * id of the users OSM account. The latter is retrieved from the OSM server with a
  * <tt>GET /api/0.6/user/details</tt> request, submitted with the user name and password
  * of the current user.
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/server/OsmApiUrlInputPanel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/server/OsmApiUrlInputPanel.java	(revision 4245)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/server/OsmApiUrlInputPanel.java	(revision 4246)
@@ -38,5 +38,5 @@
     static public final String API_URL_PROP = OsmApiUrlInputPanel.class.getName() + ".apiUrl";
 
-    static private final String defaulturl = "http://api.openstreetmap.org/api";
+    static public final String defaulturl = "http://api.openstreetmap.org/api";
     private JLabel lblValid;
     private JLabel lblApiUrl;
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/server/ProxyPreferencesPanel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/server/ProxyPreferencesPanel.java	(revision 4245)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/server/ProxyPreferencesPanel.java	(revision 4246)
@@ -292,5 +292,7 @@
         String policy = Main.pref.get(PROXY_POLICY, null);
         ProxyPolicy pp = ProxyPolicy.fromName(policy);
-        pp = pp == null? ProxyPolicy.NO_PROXY: pp;
+        if (pp == null) {
+            pp = ProxyPolicy.NO_PROXY;
+        }
         rbProxyPolicy.get(pp).setSelected(true);
         String value = Main.pref.get("proxy.host", null);
@@ -353,4 +355,5 @@
 
     class ProxyPolicyChangeListener implements ItemListener {
+        @Override
         public void itemStateChanged(ItemEvent arg0) {
             updateEnabledState();
Index: /trunk/src/org/openstreetmap/josm/io/auth/AbstractCredentialsAgent.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/auth/AbstractCredentialsAgent.java	(revision 4246)
+++ /trunk/src/org/openstreetmap/josm/io/auth/AbstractCredentialsAgent.java	(revision 4246)
@@ -0,0 +1,82 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.auth;
+
+import java.net.Authenticator.RequestorType;
+import java.net.PasswordAuthentication;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.openstreetmap.josm.gui.io.CredentialDialog;
+
+abstract public class AbstractCredentialsAgent implements CredentialsAgent {
+
+    Map<RequestorType, PasswordAuthentication> memoryCredentialsCache = new HashMap<RequestorType, PasswordAuthentication>();
+
+    /**
+     * @see CredentialsAgent#getCredentials(RequestorType, boolean)
+     */
+    @Override
+    public CredentialsAgentResponse getCredentials(RequestorType requestorType, boolean noSuccessWithLastResponse) throws CredentialsAgentException{
+        if (requestorType == null)
+            return null;
+        PasswordAuthentication credentials =  lookup(requestorType);
+        String username = (credentials == null || credentials.getUserName() == null) ? "" : credentials.getUserName();
+        String password = (credentials == null || credentials.getPassword() == null) ? "" : String.valueOf(credentials.getPassword());
+
+        CredentialsAgentResponse response = new CredentialsAgentResponse();
+
+        /*
+         * Last request was successful and there was no credentials stored
+         * in file (or only the username is stored).
+         * -> Try to recall credentials that have been entered
+         * manually in this session.
+         */
+        if (!noSuccessWithLastResponse && memoryCredentialsCache.containsKey(requestorType) &&
+                (credentials == null || credentials.getPassword() == null || credentials.getPassword().length == 0)) {
+            PasswordAuthentication pa = memoryCredentialsCache.get(requestorType);
+            response.setUsername(pa.getUserName());
+            response.setPassword(pa.getPassword());
+            response.setCanceled(false);
+        /*
+         * Prompt the user for credentials. This happens the first time each
+         * josm start if the user does not save the credentials to preference
+         * file (username=="") and each time after authentication failed
+         * (noSuccessWithLastResponse == true).
+         */
+        } else if (noSuccessWithLastResponse || username.equals("") || password.equals("")) {
+            CredentialDialog dialog = null;
+            switch(requestorType) {
+            case SERVER: dialog = CredentialDialog.getOsmApiCredentialDialog(username, password); break;
+            case PROXY: dialog = CredentialDialog.getHttpProxyCredentialDialog(username, password); break;
+            }
+            dialog.setVisible(true);
+            response.setCanceled(dialog.isCanceled());
+            if (dialog.isCanceled())
+                return response;
+            response.setUsername(dialog.getUsername());
+            response.setPassword(dialog.getPassword());
+            if (dialog.isSaveCredentials()) {
+                store(requestorType, new PasswordAuthentication(
+                        response.getUsername(),
+                        response.getPassword()
+                ));
+            /*
+             * User decides not to save credentials to file. Keep it
+             * in memory so we don't have to ask over and over again.
+             */
+            } else {
+                PasswordAuthentication pa = new PasswordAuthentication(dialog.getUsername(), dialog.getPassword());
+                memoryCredentialsCache.put(requestorType, pa);
+            }
+        /*
+         * We got it from file.
+         */
+        } else {
+            response.setUsername(username);
+            response.setPassword(password.toCharArray());
+            response.setCanceled(false);
+        }
+        return response;
+    }
+
+}
Index: /trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java	(revision 4245)
+++ /trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java	(revision 4246)
@@ -1,4 +1,9 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.io.auth;
+
+import java.net.Authenticator.RequestorType;
+import java.net.PasswordAuthentication;
+
+import org.openstreetmap.josm.data.oauth.OAuthToken;
 
 /**
@@ -8,6 +13,7 @@
  *
  */
-public class CredentialsManager {
-    private static CredentialsAgent instance;
+public class CredentialsManager implements CredentialsAgent {
+   
+    private static CredentialsManager instance;
 
     /**
@@ -16,9 +22,65 @@
      * @return the single credential agent used in JOSM
      */
-    static public CredentialsAgent getInstance() {
+    static public CredentialsManager getInstance() {
         if (instance == null) {
-            instance =  new JosmPreferencesCredentialAgent();
+            CredentialsAgent delegate;
+            if (agentFactory == null) {
+                delegate = new JosmPreferencesCredentialAgent();
+            } else {
+                delegate = agentFactory.getCredentialsAgent();
+            }
+            instance = new CredentialsManager(delegate);
         }
         return instance;
     }
+    
+    private static CredentialsAgentFactory agentFactory;
+
+    public interface CredentialsAgentFactory {
+        CredentialsAgent getCredentialsAgent();
+    }
+    
+    /**
+     * Plugins can register a CredentialsAgentFactory, thereby overriding
+     * JOSM's default credentials agent.
+     */
+    public static void registerCredentialsAgentFactory(CredentialsAgentFactory agentFactory) {
+        CredentialsManager.agentFactory = agentFactory;
+        CredentialsManager.instance = null;
+    }
+
+    /*****
+     * non-static fields and methods
+     */
+    
+    private CredentialsAgent delegate;
+
+    public CredentialsManager(CredentialsAgent delegate) {
+        this.delegate = delegate;
+    }
+
+    @Override
+    public PasswordAuthentication lookup(RequestorType requestorType) throws CredentialsAgentException {
+        return delegate.lookup(requestorType);
+    }
+
+    @Override
+    public void store(RequestorType requestorType, PasswordAuthentication credentials) throws CredentialsAgentException {
+        delegate.store(requestorType, credentials);
+    }
+
+    @Override
+    public CredentialsAgentResponse getCredentials(RequestorType requestorType, boolean noSuccessWithLastResponse) throws CredentialsAgentException {
+        return delegate.getCredentials(requestorType, noSuccessWithLastResponse);
+    }
+
+    @Override
+    public OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException {
+        return delegate.lookupOAuthAccessToken();
+    }
+
+    @Override
+    public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException {
+        delegate.storeOAuthAccessToken(accessToken);
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java	(revision 4245)
+++ /trunk/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java	(revision 4246)
@@ -4,10 +4,7 @@
 import java.net.PasswordAuthentication;
 import java.net.Authenticator.RequestorType;
-import java.util.HashMap;
-import java.util.Map;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.oauth.OAuthToken;
-import org.openstreetmap.josm.gui.io.CredentialDialog;
 import org.openstreetmap.josm.gui.preferences.server.ProxyPreferencesPanel;
 
@@ -17,7 +14,6 @@
  *
  */
-public class JosmPreferencesCredentialAgent implements CredentialsAgent {
+public class JosmPreferencesCredentialAgent extends AbstractCredentialsAgent {
 
-    Map<RequestorType, PasswordAuthentication> memoryCredentialsCache = new HashMap<RequestorType, PasswordAuthentication>();
     /**
      * @see CredentialsAgent#lookup(RequestorType)
@@ -74,71 +70,4 @@
 
     /**
-     * @see CredentialsAgent#getCredentials(RequestorType, boolean)
-     */
-    @Override
-    public CredentialsAgentResponse getCredentials(RequestorType requestorType, boolean noSuccessWithLastResponse) throws CredentialsAgentException{
-        if (requestorType == null)
-            return null;
-        PasswordAuthentication credentials =  lookup(requestorType);
-        String username = (credentials == null || credentials.getUserName() == null) ? "" : credentials.getUserName();
-        String password = (credentials == null || credentials.getPassword() == null) ? "" : String.valueOf(credentials.getPassword());
-
-        CredentialsAgentResponse response = new CredentialsAgentResponse();
-
-        /*
-         * Last request was successful and there was no credentials stored
-         * in file (or only the username is stored).
-         * -> Try to recall credentials that have been entered
-         * manually in this session.
-         */
-        if (!noSuccessWithLastResponse && memoryCredentialsCache.containsKey(requestorType) &&
-                (credentials == null || credentials.getPassword() == null || credentials.getPassword().length == 0)) {
-            PasswordAuthentication pa = memoryCredentialsCache.get(requestorType);
-            response.setUsername(pa.getUserName());
-            response.setPassword(pa.getPassword());
-            response.setCanceled(false);
-        /*
-         * Prompt the user for credentials. This happens the first time each
-         * josm start if the user does not save the credentials to preference
-         * file (username=="") and each time after authentication failed
-         * (noSuccessWithLastResponse == true).
-         */
-        } else if (noSuccessWithLastResponse || username.equals("") || password.equals("")) {
-            CredentialDialog dialog = null;
-            switch(requestorType) {
-            case SERVER: dialog = CredentialDialog.getOsmApiCredentialDialog(username, password); break;
-            case PROXY: dialog = CredentialDialog.getHttpProxyCredentialDialog(username, password); break;
-            }
-            dialog.setVisible(true);
-            response.setCanceled(dialog.isCanceled());
-            if (dialog.isCanceled())
-                return response;
-            response.setUsername(dialog.getUsername());
-            response.setPassword(dialog.getPassword());
-            if (dialog.isSaveCredentials()) {
-                store(requestorType, new PasswordAuthentication(
-                        response.getUsername(),
-                        response.getPassword()
-                ));
-            /*
-             * User decides not to save credentials to file. Keep it
-             * in memory so we don't have to ask over and over again.
-             */
-            } else {
-                PasswordAuthentication pa = new PasswordAuthentication(dialog.getUsername(), dialog.getPassword());
-                memoryCredentialsCache.put(requestorType, pa);
-            }
-        /*
-         * We got it from file.
-         */
-        } else {
-            response.setUsername(username);
-            response.setPassword(password.toCharArray());
-            response.setCanceled(false);
-        }
-        return response;
-    }
-
-    /**
      * Lookup the current OAuth Access Token to access the OSM server. Replies null, if no
      * Access Token is currently managed by this CredentialManager.
