Index: trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java	(revision 2641)
@@ -22,4 +22,5 @@
 import org.openstreetmap.josm.io.OsmServerLocationReader;
 import org.openstreetmap.josm.io.OsmServerReader;
+import org.openstreetmap.josm.io.OsmTransferCancelledException;
 import org.openstreetmap.josm.io.OsmTransferException;
 import org.xml.sax.SAXException;
@@ -94,5 +95,8 @@
                     return;
                 }
-                if (e instanceof OsmTransferException) {
+                if (e instanceof OsmTransferCancelledException) {
+                    setCanceled(true);
+                    return;
+                } else if (e instanceof OsmTransferException) {
                     rememberException(e);
                 } else {
Index: trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java	(revision 2641)
@@ -17,4 +17,5 @@
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.OsmApiInitializationException;
+import org.openstreetmap.josm.io.OsmTransferCancelledException;
 
 public class ApiPreconditionCheckerHook implements UploadHook {
@@ -38,4 +39,6 @@
                     return false;
             }
+        } catch(OsmTransferCancelledException e){
+            return false;
         } catch (OsmApiInitializationException e) {
             ExceptionDialogUtil.explainOsmTransferException(e);
Index: trunk/src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 2641)
@@ -26,4 +26,5 @@
 import java.util.Map.Entry;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.logging.Logger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -32,5 +33,4 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.preferences.ProxyPreferences;
 import org.openstreetmap.josm.tools.ColorHelper;
 
@@ -44,4 +44,5 @@
  */
 public class Preferences {
+    static private final Logger logger = Logger.getLogger(Preferences.class.getName());
 
     /**
@@ -731,14 +732,4 @@
     public void updateSystemProperties() {
         Properties sysProp = System.getProperties();
-        if (getBoolean(ProxyPreferences.PROXY_ENABLE)) {
-            sysProp.put("proxySet", "true");
-            sysProp.put("http.proxyHost", get(ProxyPreferences.PROXY_HOST));
-            sysProp.put("proxyPort", get(ProxyPreferences.PROXY_PORT));
-            if (!getBoolean(ProxyPreferences.PROXY_ANONYMOUS)) {
-                sysProp.put("proxyUser", get(ProxyPreferences.PROXY_USER));
-                sysProp.put("proxyPassword", get(ProxyPreferences.PROXY_PASS));
-            }
-
-        }
         sysProp.put("http.agent", Version.getInstance().getAgentString());
         System.setProperties(sysProp);
Index: trunk/src/org/openstreetmap/josm/data/ServerSidePreferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/ServerSidePreferences.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/data/ServerSidePreferences.java	(revision 2641)
@@ -25,6 +25,6 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.Preferences.Bookmark;
 import org.openstreetmap.josm.io.OsmConnection;
+import org.openstreetmap.josm.io.OsmTransferException;
 import org.openstreetmap.josm.io.XmlWriter;
 import org.openstreetmap.josm.tools.Base64;
@@ -66,4 +66,6 @@
                 return b.toString();
             } catch (IOException e) {
+                e.printStackTrace();
+            } catch(OsmTransferException e) {
                 e.printStackTrace();
             }
Index: trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 2641)
@@ -9,4 +9,6 @@
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
+import java.net.Authenticator;
+import java.net.ProxySelector;
 import java.util.Arrays;
 import java.util.Collection;
@@ -19,4 +21,7 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.io.DefaultProxySelector;
+import org.openstreetmap.josm.io.auth.CredentialsManagerFactory;
+import org.openstreetmap.josm.io.auth.DefaultAuthenticator;
 import org.openstreetmap.josm.plugins.PluginHandler;
 import org.openstreetmap.josm.tools.BugReportExceptionHandler;
@@ -97,4 +102,11 @@
         }
         Main.pref.updateSystemProperties();
+
+        Authenticator.setDefault(
+                new DefaultAuthenticator(
+                        CredentialsManagerFactory.getCredentialManager()
+                )
+        );
+        ProxySelector.setDefault(new DefaultProxySelector(ProxySelector.getDefault()));
 
         if (argList.contains("--help") || argList.contains("-?") || argList.contains("-h")) {
Index: trunk/src/org/openstreetmap/josm/gui/io/CredentialDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/CredentialDialog.java	(revision 2641)
+++ trunk/src/org/openstreetmap/josm/gui/io/CredentialDialog.java	(revision 2641)
@@ -0,0 +1,321 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.KeyStroke;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.JMultilineLabel;
+import org.openstreetmap.josm.gui.SideButton;
+import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
+import org.openstreetmap.josm.gui.help.HelpUtil;
+import org.openstreetmap.josm.io.OsmApi;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.WindowGeometry;
+
+public class CredentialDialog extends JDialog {
+
+    static public CredentialDialog getOsmApiCredentialDialog(String username, String password) {
+        CredentialDialog dialog = new CredentialDialog();
+        dialog.prepareForOsmApiCredentials(username, password);
+        dialog.pack();
+        return dialog;
+    }
+
+    static public CredentialDialog getHttpProxyCredentialDialog(String username, String password) {
+        CredentialDialog dialog = new CredentialDialog();
+        dialog.prepareForProxyCredentials(username, password);
+        dialog.pack();
+        return dialog;
+    }
+
+    private boolean canceled;
+    private CredentialPanel pnlCredentials;
+
+    public boolean isCanceled() {
+        return canceled;
+    }
+
+    protected void setCanceled(boolean canceled) {
+        this.canceled = canceled;
+    }
+
+    @Override
+    public void setVisible(boolean visible) {
+        if (visible) {
+            WindowGeometry.centerInWindow(Main.parent, new Dimension(350,300)).apply(this);
+        }
+        super.setVisible(visible);
+    }
+
+    protected JPanel createButtonPanel() {
+        JPanel pnl = new JPanel(new FlowLayout());
+        pnl.add(new SideButton(new OKAction()));
+        pnl.add(new SideButton(new CancelAction()));
+        pnl.add(new SideButton(new ContextSensitiveHelpAction(HelpUtil.ht("/Dialog/PasswordDialog"))));
+        return pnl;
+    }
+
+    protected void build() {
+        getContentPane().setLayout(new BorderLayout());
+        getContentPane().add(createButtonPanel(), BorderLayout.SOUTH);
+
+        addWindowListener(new WindowEventHander());
+        getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape");
+        getRootPane().getActionMap().put("escape", new CancelAction());
+
+        getRootPane().setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+    }
+
+    public CredentialDialog() {
+        setModal(true);
+        try {
+            setAlwaysOnTop(true);
+        } catch(SecurityException e) {
+            System.out.println(tr("Warning: failed to put Credential Dialog always on top. Caught security exception."));
+        }
+        build();
+    }
+
+    public void prepareForOsmApiCredentials(String username, String password) {
+        setTitle(tr("Enter credentials for OSM API"));
+        getContentPane().add(pnlCredentials = new OsmApiCredentialsPanel(), BorderLayout.CENTER);
+        pnlCredentials.init(username, password);
+        validate();
+    }
+
+    public void prepareForProxyCredentials(String username, String password) {
+        setTitle(tr("Enter credentials for HTTP proxy"));
+        getContentPane().add(pnlCredentials = new HttpProxyCredentialsPanel(), BorderLayout.CENTER);
+        pnlCredentials.init(username, password);
+        validate();
+    }
+
+    public String getUsername() {
+        if (pnlCredentials== null) return null;
+        return pnlCredentials.getUserName();
+    }
+
+    public char[] getPassword() {
+        if (pnlCredentials== null) return null;
+        return pnlCredentials.getPassword();
+    }
+
+    public boolean isSaveCredentials() {
+        if (pnlCredentials== null) return false;
+        return pnlCredentials.isSaveCredentials();
+    }
+
+    private static class CredentialPanel extends JPanel {
+        protected JTextField tfUserName;
+        protected JPasswordField tfPassword;
+        protected JCheckBox cbSaveCredentials;
+        protected JMultilineLabel lblHeading;
+        protected JMultilineLabel lblWarning;
+
+        protected void build() {
+            tfUserName = new JTextField(20);
+            tfPassword = new JPasswordField(20);
+            tfUserName.addFocusListener(new SelectAllOnFocusHandler());
+            tfPassword.addFocusListener(new SelectAllOnFocusHandler());
+            cbSaveCredentials =  new JCheckBox(tr("Save user and password (unencrypted)"));
+
+            setLayout(new GridBagLayout());
+            GridBagConstraints gc = new GridBagConstraints();
+            gc.gridwidth = 2;
+            gc.gridheight = 1;
+            gc.fill = GridBagConstraints.HORIZONTAL;
+            gc.weightx = 1.0;
+            gc.weighty = 0.0;
+            gc.insets = new Insets(0,0,10,0);
+            add(lblHeading = new JMultilineLabel(""), gc);
+
+            gc.gridx = 0;
+            gc.gridy = 1;
+            gc.gridwidth = 1;
+            gc.gridheight = 1;
+            gc.fill = GridBagConstraints.HORIZONTAL;
+            gc.weightx = 0.0;
+            gc.weighty = 0.0;
+            gc.insets = new Insets(0,0,10,10);
+            add(new JLabel(tr("Username")), gc);
+            gc.gridx = 1;
+            gc.gridy = 1;
+            gc.weightx = 1.0;
+            add(tfUserName, gc);
+            gc.gridx = 0;
+            gc.gridy = 2;
+            gc.weightx = 0.0;
+            add(new JLabel(tr("Password")), gc);
+
+            gc.gridx = 1;
+            gc.gridy = 2;
+            gc.weightx = 0.0;
+            add(tfPassword, gc);
+
+            gc.gridx = 0;
+            gc.gridy = 3;
+            gc.gridwidth = 2;
+            gc.gridheight = 1;
+            gc.fill = GridBagConstraints.BOTH;
+            gc.weightx = 1.0;
+            gc.weighty = 0.0;
+            lblWarning = new JMultilineLabel(tr(""));
+            lblWarning.setFont(lblWarning.getFont().deriveFont(Font.ITALIC));
+            add(lblWarning, gc);
+
+            gc.gridx = 0;
+            gc.gridy = 4;
+            gc.weighty = 0.0;
+            add(cbSaveCredentials, gc);
+
+            // consume the remaining space
+            gc.gridx = 0;
+            gc.gridy = 5;
+            gc.weighty = 1.0;
+            add(new JPanel(),gc);
+
+        }
+
+        public CredentialPanel() {
+        }
+
+        public void init(String username, String password) {
+            username = username == null ? "" : username;
+            password = password == null ? "" : password;
+            tfUserName.setText(username);
+            tfPassword.setText(password);
+            cbSaveCredentials.setSelected(!username.equals("") && ! password.equals(""));
+        }
+
+        public void startUserInput() {
+            tfUserName.requestFocusInWindow();
+        }
+
+        public String getUserName() {
+            return tfUserName.getText();
+        }
+
+        public char[] getPassword() {
+            return tfPassword.getPassword();
+        }
+
+        public boolean isSaveCredentials() {
+            return cbSaveCredentials.isSelected();
+        }
+    }
+
+    private static class OsmApiCredentialsPanel extends CredentialPanel {
+
+        @Override
+        protected void build() {
+            super.build();
+            tfUserName.setToolTipText(tr("Please enter the user name of your OSM account"));
+            tfPassword.setToolTipText(tr("Please enter the password name of your OSM account"));
+            lblHeading.setText(
+                    tr("<html>Authenticating at the OSM API ''{0}'' failed. Please enter a valid username and a valid password.</html>",
+                            OsmApi.getOsmApi().getBaseUrl()));
+            lblWarning.setText(tr("Warning: The password is transferred unencrypted."));
+        }
+
+        public OsmApiCredentialsPanel() {
+            build();
+        }
+    }
+
+    private static class HttpProxyCredentialsPanel extends CredentialPanel {
+        @Override
+        protected void build() {
+            super.build();
+            tfUserName.setToolTipText(tr("Please enter the user name for authenticating at your proxy server"));
+            tfPassword.setToolTipText(tr("Please enter the password for authenticating at your proxy server"));
+            lblHeading.setText(
+                    tr("<html>Authenticating at the HTTP proxy ''{0}'' failed. Please enter a valid username and a valid password.</html>",
+                            System.getProperty("http.proxyHost") + ":" + System.getProperty("http.proxyPort")));
+            lblWarning.setText(tr("<html>Warning: depending on the authentication method the proxy server uses the password may be transferred unencrypted.</html>"));
+        }
+
+        public HttpProxyCredentialsPanel() {
+            build();
+        }
+    }
+
+    static private class SelectAllOnFocusHandler extends FocusAdapter {
+        @Override
+        public void focusGained(FocusEvent e) {
+            if (e.getSource() instanceof JTextField) {
+                JTextField tf = (JTextField)e.getSource();
+                tf.selectAll();
+            }
+        }
+    }
+
+    class OKAction extends AbstractAction {
+        public OKAction() {
+            putValue(NAME, tr("Authenticate"));
+            putValue(SHORT_DESCRIPTION, tr("Authenticate with the supplied username and password"));
+            putValue(SMALL_ICON, ImageProvider.get("ok"));
+        }
+
+        public void actionPerformed(ActionEvent arg0) {
+            setCanceled(false);
+            setVisible(false);
+        }
+    }
+
+    class CancelAction extends AbstractAction {
+        public CancelAction() {
+            putValue(NAME, tr("Cancel"));
+            putValue(SHORT_DESCRIPTION, tr("Cancel authentication"));
+            putValue(SMALL_ICON, ImageProvider.get("cancel"));
+        }
+
+        public void cancel() {
+            setCanceled(true);
+            setVisible(false);
+        }
+
+        public void actionPerformed(ActionEvent arg0) {
+            cancel();
+        }
+    }
+
+    class WindowEventHander extends WindowAdapter {
+
+        @Override
+        public void windowActivated(WindowEvent e) {
+            if (pnlCredentials != null) {
+                pnlCredentials.startUserInput();
+            }
+        }
+
+        @Override
+        public void windowClosing(WindowEvent e) {
+            new CancelAction().cancel();
+        }
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java	(revision 2641)
@@ -29,4 +29,5 @@
 import org.openstreetmap.josm.io.OsmApiPrimitiveGoneException;
 import org.openstreetmap.josm.io.OsmServerWriter;
+import org.openstreetmap.josm.io.OsmTransferCancelledException;
 import org.openstreetmap.josm.io.OsmTransferException;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -239,4 +240,7 @@
                     //
                     break;
+                } catch(OsmTransferCancelledException e) {
+                    uploadCancelled = true;
+                    return;
                 } catch(OsmApiPrimitiveGoneException e) {
                     // try to recover from  410 Gone
Index: trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java	(revision 2641)
@@ -44,5 +44,5 @@
     // 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."),true);
+    public final JPanel connection = createPreferenceTab("connection", I18n.tr("Connection Settings"), I18n.tr("Connection Settings for the OSM server."),false);
     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: trunk/src/org/openstreetmap/josm/gui/preferences/ProxyPreferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/ProxyPreferences.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/ProxyPreferences.java	(revision 2641)
@@ -4,11 +4,19 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.Box;
-import javax.swing.JCheckBox;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.net.ProxySelector;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.ButtonGroup;
 import javax.swing.JLabel;
+import javax.swing.JPanel;
 import javax.swing.JPasswordField;
+import javax.swing.JRadioButton;
 import javax.swing.JSeparator;
 import javax.swing.JTextField;
@@ -16,7 +24,11 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.JMultilineLabel;
+import org.openstreetmap.josm.io.DefaultProxySelector;
 import org.openstreetmap.josm.tools.GBC;
 
 public class ProxyPreferences implements PreferenceSetting {
+
+
 
     public static class Factory implements PreferenceSettingFactory {
@@ -26,69 +38,296 @@
     }
 
-    public static final String PROXY_ENABLE = "proxy.enable";
-    public static final String PROXY_HOST = "proxy.host";
-    public static final String PROXY_PORT = "proxy.port";
-    public static final String PROXY_ANONYMOUS = "proxy.anonymous";
+    public enum ProxyPolicy {
+        NO_PROXY("no-proxy"),
+        USE_SYSTEM_SETTINGS("use-system-settings"),
+        USE_HTTP_PROXY("use-http-proxy"),
+        USE_SOCKS_PROXY("use-socks-proxy");
+
+        private String policyName;
+        ProxyPolicy(String policyName) {
+            this.policyName = policyName;
+        }
+
+        public String getName() {
+            return policyName;
+        }
+
+        static public ProxyPolicy fromName(String policyName) {
+            if (policyName == null) return null;
+            policyName = policyName.trim().toLowerCase();
+            for(ProxyPolicy pp: values()) {
+                if (pp.getName().equals(policyName))
+                    return pp;
+            }
+            return null;
+        }
+    }
+
+    public static final String PROXY_POLICY = "proxy.policy";
+    public static final String PROXY_HTTP_HOST = "proxy.http.host";
+    public static final String PROXY_HTTP_PORT = "proxy.http.port";
+    public static final String PROXY_SOCKS_HOST = "proxy.socks.host";
+    public static final String PROXY_SOCKS_PORT = "proxy.socks.port";
     public static final String PROXY_USER = "proxy.user";
     public static final String PROXY_PASS = "proxy.pass";
 
-    private JCheckBox proxyEnable = new JCheckBox(tr("Enable proxy server"));
-    private JTextField proxyHost = new JTextField(20);
-    private JTextField proxyPort = new JTextField(5);
-    private JCheckBox proxyAnonymous = new JCheckBox(tr("Anonymous"));
-    private JTextField proxyUser = new JTextField(20);
-    private JPasswordField proxyPass = new JPasswordField(20);
+    private ButtonGroup bgProxyPolicy;
+    private Map<ProxyPolicy, JRadioButton> rbProxyPolicy;
+    private JTextField tfProxyHttpHost;
+    private JTextField tfProxyHttpPort;
+    private JTextField tfProxySocksHost;
+    private JTextField tfProxySocksPort;
+    private JTextField tfProxyHttpUser;
+    private JPasswordField tfProxyHttpPassword;
+
+    protected JPanel buildHttpProxyConfigurationPanel() {
+        JPanel pnl = new JPanel(new GridBagLayout()) {
+            @Override
+            public Dimension getMinimumSize() {
+                return getPreferredSize();
+            }
+        };
+        GridBagConstraints gc = new GridBagConstraints();
+
+        gc.anchor = GridBagConstraints.WEST;
+        gc.insets = new Insets(5,5,0,0);
+        pnl.add(new JLabel("Host:"), gc);
+
+        gc.gridx = 1;
+        pnl.add(tfProxyHttpHost = new JTextField(20),gc);
+
+        gc.gridy = 1;
+        gc.gridx = 0;
+        pnl.add(new JLabel("Port:"), gc);
+
+        gc.gridx = 1;
+        gc.weightx = 0.0;
+        pnl.add(tfProxyHttpPort = new JTextField(5),gc);
+
+        gc.gridy = 2;
+        gc.gridx = 0;
+        gc.gridwidth = 2;
+        gc.fill = GridBagConstraints.BOTH;
+        gc.weightx = 1.0;
+        gc.weighty = 1.0;
+        pnl.add(new JMultilineLabel(tr("Please enter a username and a password if your proxy requires authentication.")), gc);
+
+        gc.gridy = 3;
+        gc.gridx = 0;
+        gc.gridwidth = 1;
+        gc.weightx = 0.0;
+        gc.fill = GridBagConstraints.NONE;
+        pnl.add(new JLabel("User:"), gc);
+
+        gc.gridy = 3;
+        gc.gridx = 1;
+        pnl.add(tfProxyHttpUser = new JTextField(20),gc);
+
+        gc.gridy = 4;
+        gc.gridx = 0;
+        pnl.add(new JLabel("Password:"), gc);
+
+        gc.gridx = 1;
+        pnl.add(tfProxyHttpPassword = new JPasswordField(20),gc);
+        return pnl;
+    }
+
+    protected JPanel buildSocksProxyConfigurationPanel() {
+        JPanel pnl = new JPanel(new GridBagLayout()) {
+            @Override
+            public Dimension getMinimumSize() {
+                return getPreferredSize();
+            }
+        };
+        GridBagConstraints gc = new GridBagConstraints();
+        gc.anchor = GridBagConstraints.WEST;
+        gc.insets = new Insets(5,5,0,0);
+        pnl.add(new JLabel("Host:"), gc);
+
+        gc.gridx = 1;
+        pnl.add(tfProxySocksHost = new JTextField(20),gc);
+
+        gc.gridy = 1;
+        gc.gridx = 0;
+        pnl.add(new JLabel("Port:"), gc);
+
+        gc.gridx = 1;
+        pnl.add(tfProxySocksPort = new JTextField(5),gc);
+
+        // add an extra spacer, otherwise the layout is broken
+        gc.gridy = 2;
+        gc.gridx = 0;
+        gc.gridwidth = 2;
+        gc.fill = GridBagConstraints.BOTH;
+        gc.weightx = 1.0;
+        gc.weighty = 1.0;
+        pnl.add(new JPanel(), gc);
+        return pnl;
+    }
+
+    protected JPanel buildProxySettingsPanel() {
+        JPanel pnl = new JPanel(new GridBagLayout());
+        GridBagConstraints gc = new GridBagConstraints();
+
+        bgProxyPolicy = new ButtonGroup();
+        rbProxyPolicy = new HashMap<ProxyPolicy, JRadioButton>();
+        ProxyPolicyChangeListener policyChangeListener = new ProxyPolicyChangeListener();
+        for (ProxyPolicy pp: ProxyPolicy.values()) {
+            rbProxyPolicy.put(pp, new JRadioButton());
+            bgProxyPolicy.add(rbProxyPolicy.get(pp));
+            rbProxyPolicy.get(pp).addItemListener(policyChangeListener);
+        }
+        gc.gridx = 0;
+        gc.gridy = 0;
+        gc.fill = GridBagConstraints.NONE;
+        gc.anchor = GridBagConstraints.FIRST_LINE_START;
+        pnl.add(rbProxyPolicy.get(ProxyPolicy.NO_PROXY),gc);
+        gc.gridx = 1;
+        gc.fill = GridBagConstraints.HORIZONTAL;
+        gc.weightx = 1.0;
+        pnl.add(new JLabel(tr("No proxy")), gc);
+
+        gc.gridx = 0;
+        gc.gridy = 1;
+        gc.fill = GridBagConstraints.NONE;
+        gc.anchor = GridBagConstraints.FIRST_LINE_START;
+        pnl.add(rbProxyPolicy.get(ProxyPolicy.USE_SYSTEM_SETTINGS),gc);
+        gc.gridx = 1;
+        gc.fill = GridBagConstraints.HORIZONTAL;
+        gc.weightx = 1.0;
+        gc.weighty = 0.0;
+        String msg;
+        if (DefaultProxySelector.willJvmRetrieveSystemProxies()) {
+            msg = tr("Use standard system settings");
+        } else {
+            msg = tr("Use standard system settings (disabled. Start JOSM with <tt>-Djava.net.useSystemProxies=true</tt> to enable)");
+        }
+        pnl.add(new JMultilineLabel("<html>" + msg + "</html>"), gc);
+
+        gc.gridx = 0;
+        gc.gridy = 2;
+        gc.fill = GridBagConstraints.NONE;
+        gc.anchor = GridBagConstraints.FIRST_LINE_START;
+        pnl.add(rbProxyPolicy.get(ProxyPolicy.USE_HTTP_PROXY),gc);
+        gc.gridx = 1;
+        gc.fill = GridBagConstraints.HORIZONTAL;
+        gc.weightx = 1.0;
+        pnl.add(new JLabel(tr("Manually configure a HTTP proxy")),gc);
+
+        gc.gridx = 1;
+        gc.gridy = 3;
+        gc.fill = GridBagConstraints.HORIZONTAL;
+        gc.weightx = 1.0;
+        gc.weighty = 0.0;
+        pnl.add(buildHttpProxyConfigurationPanel(),gc);
+
+        gc.gridx = 0;
+        gc.gridy = 4;
+        gc.fill = GridBagConstraints.NONE;
+        gc.anchor = GridBagConstraints.FIRST_LINE_START;
+        pnl.add(rbProxyPolicy.get(ProxyPolicy.USE_SOCKS_PROXY),gc);
+        gc.gridx = 1;
+        gc.fill = GridBagConstraints.HORIZONTAL;
+        gc.weightx = 1.0;
+        pnl.add(new JLabel(tr("Use a SOCKS proxy")),gc);
+
+        gc.gridx = 1;
+        gc.gridy = 5;
+        gc.fill = GridBagConstraints.BOTH;
+        gc.anchor = GridBagConstraints.WEST;
+        gc.weightx = 1.0;
+        gc.weighty = 0.0;
+        pnl.add(buildSocksProxyConfigurationPanel(),gc);
+
+        return pnl;
+    }
+
+    protected void initFromPreferences() {
+        String policy = Main.pref.get(PROXY_POLICY, null);
+        ProxyPolicy pp = ProxyPolicy.fromName(policy);
+        pp = pp == null? ProxyPolicy.NO_PROXY: pp;
+        rbProxyPolicy.get(pp).setSelected(true);
+        String value = Main.pref.get("proxy.host", null);
+        if (value != null) {
+            // legacy support
+            tfProxyHttpHost.setText(value);
+            Main.pref.put("proxy.host", null);
+        } else {
+            tfProxyHttpHost.setText(Main.pref.get(PROXY_HTTP_HOST, ""));
+        }
+        value = Main.pref.get("proxy.port", null);
+        if (value != null) {
+            // legacy support
+            tfProxyHttpPort.setText(value);
+            Main.pref.put("proxy.port", null);
+        } else {
+            tfProxyHttpPort.setText(Main.pref.get(PROXY_HTTP_PORT, ""));
+        }
+        tfProxySocksHost.setText(Main.pref.get(PROXY_SOCKS_HOST, ""));
+        tfProxySocksPort.setText(Main.pref.get(PROXY_SOCKS_PORT, ""));
+        tfProxyHttpUser.setText(Main.pref.get(PROXY_USER, ""));
+        tfProxyHttpPassword.setText(Main.pref.get(PROXY_PASS, ""));
+
+        if (pp.equals(ProxyPolicy.USE_SYSTEM_SETTINGS) && ! DefaultProxySelector.willJvmRetrieveSystemProxies()) {
+            System.err.println(tr("Warning: JOSM is configured to use proxies from the system setting, but the JVM is not configured to retrieve them. Resetting preferences to ''No proxy''"));
+            pp = ProxyPolicy.NO_PROXY;
+            rbProxyPolicy.get(pp).setSelected(true);
+        }
+    }
+
+    protected void updateEnabledState() {
+        tfProxyHttpHost.setEnabled(rbProxyPolicy.get(ProxyPolicy.USE_HTTP_PROXY).isSelected());
+        tfProxyHttpPort.setEnabled(rbProxyPolicy.get(ProxyPolicy.USE_HTTP_PROXY).isSelected());
+        tfProxyHttpUser.setEnabled(rbProxyPolicy.get(ProxyPolicy.USE_HTTP_PROXY).isSelected());
+        tfProxyHttpPassword.setEnabled(rbProxyPolicy.get(ProxyPolicy.USE_HTTP_PROXY).isSelected());
+        tfProxySocksHost.setEnabled(rbProxyPolicy.get(ProxyPolicy.USE_SOCKS_PROXY).isSelected());
+        tfProxySocksPort.setEnabled(rbProxyPolicy.get(ProxyPolicy.USE_SOCKS_PROXY).isSelected());
+
+        rbProxyPolicy.get(ProxyPolicy.USE_SYSTEM_SETTINGS).setEnabled(DefaultProxySelector.willJvmRetrieveSystemProxies());
+    }
+
+    class ProxyPolicyChangeListener implements ItemListener {
+        public void itemStateChanged(ItemEvent arg0) {
+            updateEnabledState();
+        }
+    }
 
     public void addGui(PreferenceDialog gui) {
-        proxyEnable.setSelected(Main.pref.getBoolean(PROXY_ENABLE));
-        proxyEnable.addActionListener(new ActionListener(){
-            public void actionPerformed(ActionEvent e) {
-                proxyHost.setEnabled(proxyEnable.isSelected());
-                proxyPort.setEnabled(proxyEnable.isSelected());
-                proxyAnonymous.setEnabled(proxyEnable.isSelected());
-                proxyUser.setEnabled(proxyEnable.isSelected() && !proxyAnonymous.isSelected());
-                proxyPass.setEnabled(proxyEnable.isSelected() && !proxyAnonymous.isSelected());
-            }
-        });
-        proxyHost.setEnabled(Main.pref.getBoolean(PROXY_ENABLE));
-        proxyHost.setText(Main.pref.get(PROXY_HOST));
-        proxyPort.setEnabled(Main.pref.getBoolean(PROXY_ENABLE));
-        proxyPort.setText(Main.pref.get(PROXY_PORT));
-        proxyAnonymous.setEnabled(Main.pref.getBoolean(PROXY_ENABLE));
-        proxyAnonymous.setSelected(Main.pref.getBoolean(PROXY_ANONYMOUS));
-        proxyAnonymous.addActionListener(new ActionListener(){
-            public void actionPerformed(ActionEvent e) {
-                proxyUser.setEnabled(proxyEnable.isSelected() && !proxyAnonymous.isSelected());
-                proxyPass.setEnabled(proxyEnable.isSelected() && !proxyAnonymous.isSelected());
-            }
-        });
-        proxyUser.setEnabled(Main.pref.getBoolean(PROXY_ENABLE) && (Main.pref.getBoolean(PROXY_ANONYMOUS)));
-        proxyUser.setText(Main.pref.get(PROXY_USER));
-        proxyPass.setEnabled(Main.pref.getBoolean(PROXY_ENABLE) && (Main.pref.getBoolean(PROXY_ANONYMOUS)));
-        proxyPass.setText(Main.pref.get(PROXY_USER));
-
         gui.connection.add(new JSeparator(SwingConstants.HORIZONTAL), GBC.eol().fill(GBC.HORIZONTAL));
         gui.connection.add(new JLabel(tr("Proxy Settings")), GBC.eol());
-        gui.connection.add(proxyEnable, GBC.eol().insets(20, 0, 0, 0));
-        gui.connection.add(new JLabel(tr("Proxy server host")), GBC.std());
-        gui.connection.add(proxyHost, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-        gui.connection.add(new JLabel(tr("Proxy server port")), GBC.std());
-        gui.connection.add(proxyPort, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-        gui.connection.add(proxyAnonymous, GBC.eop().insets(20, 0, 0, 0));
-        gui.connection.add(new JLabel(tr("Proxy server username")), GBC.std());
-        gui.connection.add(proxyUser, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-        gui.connection.add(new JLabel(tr("Proxy server password")), GBC.std());
-        gui.connection.add(proxyPass, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-
-        gui.connection.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
+        gui.connection.add(buildProxySettingsPanel(), GBC.eol().insets(20,10,0,0));
+
+        initFromPreferences();
+        updateEnabledState();
     }
 
     public boolean ok() {
-        Main.pref.put(PROXY_ENABLE, proxyEnable.isSelected());
-        Main.pref.put(PROXY_HOST, proxyHost.getText());
-        Main.pref.put(PROXY_PORT, proxyPort.getText());
-        Main.pref.put(PROXY_ANONYMOUS, proxyAnonymous.isSelected());
-        Main.pref.put(PROXY_USER, proxyUser.getText());
-        Main.pref.put(PROXY_PASS, new String(proxyPass.getPassword()));
+        ProxyPolicy policy = null;
+        for (ProxyPolicy pp: ProxyPolicy.values()) {
+            if (rbProxyPolicy.get(pp).isSelected()) {
+                policy = pp;
+                break;
+            }
+        }
+        if (policy == null) {
+            policy = ProxyPolicy.NO_PROXY;
+        }
+        Main.pref.put(PROXY_POLICY, policy.getName());
+        Main.pref.put(PROXY_HTTP_HOST, tfProxyHttpHost.getText());
+        Main.pref.put(PROXY_HTTP_PORT, tfProxyHttpPort.getText());
+        Main.pref.put(PROXY_SOCKS_HOST, tfProxySocksHost.getText());
+        Main.pref.put(PROXY_SOCKS_PORT, tfProxySocksPort.getText());
+        Main.pref.put(PROXY_USER, tfProxyHttpUser.getText());
+        Main.pref.put(PROXY_PASS, String.valueOf(tfProxyHttpPassword.getPassword()));
+
+        // remove these legacy property keys
+        Main.pref.put("proxy.anonymous", null);
+        Main.pref.put("proxy.enable", null);
+
+        // update the proxy selector
+        ProxySelector selector = ProxySelector.getDefault();
+        if (selector instanceof DefaultProxySelector) {
+            ((DefaultProxySelector)selector).initFromPreferences();
+        }
         return false;
     }
Index: trunk/src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/ServerAccessPreference.java	(revision 2641)
@@ -2,6 +2,19 @@
 package org.openstreetmap.josm.gui.preferences;
 
-import org.openstreetmap.josm.io.CredentialsManager;
-import org.openstreetmap.josm.io.OsmConnection;
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Font;
+import java.net.PasswordAuthentication;
+import java.net.Authenticator.RequestorType;
+
+import javax.swing.JLabel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.io.auth.CredentialsManager;
+import org.openstreetmap.josm.io.auth.CredentialsManagerException;
+import org.openstreetmap.josm.io.auth.CredentialsManagerFactory;
+import org.openstreetmap.josm.tools.GBC;
 
 public class ServerAccessPreference implements PreferenceSetting {
@@ -14,15 +27,64 @@
 
     /**
-     * Provide username and password input editfields.
-     * Store the values if user hits OK.
+     * Editfield for the Base url to the REST API from OSM.
      */
-    private CredentialsManager.PreferenceAdditions credentialsPA = OsmConnection.credentialsManager.newPreferenceAdditions();
+    final private JTextField osmDataServerURL = new JTextField(20);
+    /**
+     * Editfield for the username to the OSM account.
+     */
+    final private JTextField osmDataUsername = new JTextField(20);
+    /**
+     * Passwordfield for the userpassword of the REST API.
+     */
+    final private JPasswordField osmDataPassword = new JPasswordField(20);
 
     public void addGui(PreferenceDialog gui) {
-        credentialsPA.addPreferenceOptions(gui.connection);
+        CredentialsManager cm = CredentialsManagerFactory.getCredentialManager();
+        String oldServerURL = Main.pref.get("osm-server.url", "http://api.openstreetmap.org/api");
+        String oldUsername;
+        String oldPassword;
+        try {
+            PasswordAuthentication credentials =  cm.lookup(RequestorType.SERVER);
+            oldUsername = (credentials == null | credentials.getUserName() == null) ? "" : credentials.getUserName();
+            oldPassword = (credentials == null | credentials.getPassword() == null) ? "" : String.valueOf(credentials.getPassword());
+        } catch(CredentialsManagerException e) {
+            e.printStackTrace();
+            oldUsername = "";
+            oldPassword = "";
+        }
+
+        osmDataServerURL.setText(oldServerURL);
+        osmDataUsername.setText(oldUsername);
+        osmDataPassword.setText(oldPassword);
+        osmDataServerURL.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(osmDataServerURL, 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));
     }
 
     public boolean ok() {
-        credentialsPA.preferencesChanged();
+        CredentialsManager cm = CredentialsManagerFactory.getCredentialManager();
+        Main.pref.put("osm-server.url", osmDataServerURL.getText());
+        try {
+            cm.store(RequestorType.SERVER, new PasswordAuthentication(
+                    osmDataUsername.getText(),
+                    osmDataPassword.getPassword()
+            ));
+        } catch(CredentialsManagerException e) {
+            // FIXME: Message dialog with an error message?
+            e.printStackTrace();
+        }
         return false;
     }
Index: trunk/src/org/openstreetmap/josm/io/CredentialsManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/CredentialsManager.java	(revision 2638)
+++ 	(revision )
@@ -1,61 +1,0 @@
-// 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 {
-    enum Key {
-        OSM_SERVER_URL("url"),
-        USERNAME("username"),
-        PASSWORD("password");
-        final private String pname;
-        private Key(String name) {
-            pname = name;
-        }
-        @Override public String toString() {
-            return pname;
-        }
-    };
-
-    /**
-     * Should throw or return non-null, possibly empty String.
-     */
-    public String lookup(Key key) throws CMException;
-
-    /**
-     * May silently fail to store.
-     */
-    public void store(Key key, String secret) 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: trunk/src/org/openstreetmap/josm/io/DefaultProxySelector.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/DefaultProxySelector.java	(revision 2641)
+++ trunk/src/org/openstreetmap/josm/io/DefaultProxySelector.java	(revision 2641)
@@ -0,0 +1,169 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.net.Proxy.Type;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.preferences.ProxyPreferences;
+import org.openstreetmap.josm.gui.preferences.ProxyPreferences.ProxyPolicy;
+
+/**
+ * This is the default proxy selector used in JOSM.
+ * 
+ */
+public class DefaultProxySelector extends ProxySelector {
+    static private final Logger logger = Logger.getLogger(DefaultProxySelector.class.getName());
+
+    /**
+     * The {@see ProxySelector} provided by the JDK will retrieve proxy information
+     * from the system settings, if the system property <tt>java.net.useSystemProxies</tt>
+     * is defined <strong>at startup</strong>. It has no effect if the property is set
+     * later by the application.
+     *
+     * We therefore read the property at class loading time and remember it's value.
+     */
+    private static boolean JVM_WILL_USE_SYSTEM_PROXIES = false;
+    {
+        String v = System.getProperty("java.net.useSystemProxies");
+        if (v != null && v.equals(Boolean.TRUE.toString())) {
+            JVM_WILL_USE_SYSTEM_PROXIES = true;
+        }
+    }
+
+    /**
+     * The {@see ProxySelector} provided by the JDK will retrieve proxy information
+     * from the system settings, if the system property <tt>java.net.useSystemProxies</tt>
+     * is defined <strong>at startup</strong>. If the property is set later by the application,
+     * this has no effect.
+     * 
+     * @return true, if <tt>java.net.useSystemProxies</tt> was set to true at class initialization time
+     * 
+     */
+    public static boolean willJvmRetrieveSystemProxies() {
+        return JVM_WILL_USE_SYSTEM_PROXIES;
+    }
+
+    private ProxyPolicy proxyPolicy;
+    private InetSocketAddress httpProxySocketAddress;
+    private InetSocketAddress socksProxySocketAddress;
+    private ProxySelector delegate;
+
+    /**
+     * A typical example is:
+     * <pre>
+     *    PropertySelector delegate = PropertySelector.getDefault();
+     *    PropertySelector.setDefault(new DefaultPropertySelector(delegate));
+     * </pre>
+     * 
+     * @param delegate the proxy selector to delegate to if system settings are used. Usually
+     * this is the proxy selector found by ProxySelector.getDefault() before this proxy
+     * selector is installed
+     */
+    public DefaultProxySelector(ProxySelector delegate) {
+        this.delegate = delegate;
+        initFromPreferences();
+    }
+
+    protected int parseProxyPortValue(String property, String value) {
+        if (value == null) return 0;
+        int port = 0;
+        try {
+            port = Integer.parseInt(value);
+        } catch(NumberFormatException e){
+            System.err.println(tr("Unexpected format for port number in in preference ''{0}''. Got ''{1}''. Proxy won't be used.", property, value));
+            return 0;
+        }
+        if (port <= 0 || port >  65535) {
+            System.err.println(tr("Illegal port number in preference ''{0}''. Got {1}. Proxy won't be used.", property, port));
+            return 0;
+        }
+        return port;
+    }
+
+    /**
+     * Initializes the proxy selector from the setting in the preferences.
+     * 
+     */
+    public void initFromPreferences() {
+        String value = Main.pref.get(ProxyPreferences.PROXY_POLICY);
+        if (value == null) {
+            System.err.println(tr("Warning: no preference ''{0}'' found. Will use no proxy.", ProxyPreferences.PROXY_POLICY));
+            proxyPolicy = ProxyPolicy.NO_PROXY;
+        } else {
+            proxyPolicy= ProxyPolicy.fromName(value);
+            if (proxyPolicy == null) {
+                System.err.println(tr("Warning: unexpected value for preference ''{0}'' found. Got ''{1}''. Will use no proxy.", ProxyPreferences.PROXY_POLICY, value));
+                proxyPolicy = ProxyPolicy.NO_PROXY;
+            }
+        }
+        String host = Main.pref.get(ProxyPreferences.PROXY_HTTP_HOST, null);
+        int port = parseProxyPortValue(ProxyPreferences.PROXY_HTTP_PORT, Main.pref.get(ProxyPreferences.PROXY_HTTP_PORT, null));
+        if (host != null && ! host.trim().equals("") && port > 0) {
+            httpProxySocketAddress = new InetSocketAddress(host,port);
+        } else {
+            httpProxySocketAddress = null;
+            if (proxyPolicy.equals(ProxyPolicy.USE_HTTP_PROXY)) {
+                System.err.println(tr("Warning: Unexpected parameters for HTTP proxy. Got host ''{0}'' and port ''{1}''. Proxy won't be used", host, port));
+            }
+        }
+
+        host = Main.pref.get(ProxyPreferences.PROXY_SOCKS_HOST, null);
+        port = parseProxyPortValue(ProxyPreferences.PROXY_SOCKS_PORT, Main.pref.get(ProxyPreferences.PROXY_SOCKS_PORT, null));
+        if (host != null && ! host.trim().equals("") && port > 0) {
+            socksProxySocketAddress = new InetSocketAddress(host,port);
+        } else {
+            socksProxySocketAddress = null;
+            if (proxyPolicy.equals(ProxyPolicy.USE_SOCKS_PROXY)) {
+                System.err.println(tr("Warning: Unexpected parameters for SOCKS proxy. Got host ''{0}'' and port ''{1}''. Proxy won't be used", host, port));
+            }
+        }
+    }
+
+    @Override
+    public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+        // Just log something. The network stack will also throw an exception which will be caught
+        // somewhere else
+        //
+        System.out.println(tr("Error: Connection to proxy ''{0}'' for URI ''{1}'' failed. Exception was: {2}", sa.toString(), uri.toString(), ioe.toString()));
+    }
+
+    @Override
+    public List<Proxy> select(URI uri) {
+        Proxy proxy;
+        switch(proxyPolicy) {
+        case USE_SYSTEM_SETTINGS:
+            if (!JVM_WILL_USE_SYSTEM_PROXIES) {
+                System.err.println(tr("Warning: the JVM is not configured to lookup proxies from the system settings. The property ''java.net.useSystemProxies'' was missing at startup time. Won't use a proxy."));
+                return Collections.singletonList(Proxy.NO_PROXY);
+            }
+            // delegate to the former proxy selector
+            List<Proxy> ret = delegate.select(uri);
+            return ret;
+        case NO_PROXY:
+            return Collections.singletonList(Proxy.NO_PROXY);
+        case USE_HTTP_PROXY:
+            if (httpProxySocketAddress == null)
+                return Collections.singletonList(Proxy.NO_PROXY);
+            proxy = new Proxy(Type.HTTP, httpProxySocketAddress);
+            return Collections.singletonList(proxy);
+        case USE_SOCKS_PROXY:
+            if (socksProxySocketAddress == null)
+                return Collections.singletonList(Proxy.NO_PROXY);
+            proxy = new Proxy(Type.SOCKS, socksProxySocketAddress);
+            return Collections.singletonList(proxy);
+        }
+        // should not happen
+        return null;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/MultiPartFormOutputStream.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/MultiPartFormOutputStream.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/io/MultiPartFormOutputStream.java	(revision 2641)
@@ -92,5 +92,4 @@
         this.out = new DataOutputStream(os);
         this.boundary = boundary;
-        initAuthentication();
     }
 
Index: trunk/src/org/openstreetmap/josm/io/OsmApi.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 2641)
@@ -23,4 +23,5 @@
 import java.util.HashMap;
 
+import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParserFactory;
 
@@ -147,9 +148,8 @@
      * @exception OsmApiInitializationException thrown, if an exception occurs
      */
-    public void initialize(ProgressMonitor monitor) throws OsmApiInitializationException {
+    public void initialize(ProgressMonitor monitor) throws OsmApiInitializationException, OsmTransferCancelledException {
         if (initialized)
             return;
         cancel = false;
-        initAuthentication();
         try {
             String s = sendRequest("GET", "capabilities", null,monitor, false);
@@ -169,7 +169,18 @@
             osmWriter.setVersion(version);
             initialized = true;
-        } catch (Exception ex) {
+        } catch(IOException e) {
             initialized = false;
-            throw new OsmApiInitializationException(ex);
+            throw new OsmApiInitializationException(e);
+        } catch(SAXException e) {
+            initialized = false;
+            throw new OsmApiInitializationException(e);
+        } catch(ParserConfigurationException e) {
+            initialized = false;
+            throw new OsmApiInitializationException(e);
+        } catch(OsmTransferCancelledException e){
+            throw e;
+        } catch(OsmTransferException e) {
+            initialized = false;
+            throw new OsmApiInitializationException(e);
         }
     }
@@ -436,5 +447,5 @@
                 monitor.setCustomText(tr("Starting retry {0} of {1} in {2} seconds ...", getMaxRetries() - retry,getMaxRetries(), 10-i));
             }
-            if (cancel || isAuthCancelled())
+            if (cancel)
                 throw new OsmTransferCancelledException();
             try {
@@ -563,4 +574,10 @@
                 case HttpURLConnection.HTTP_GONE:
                     throw new OsmApiPrimitiveGoneException(errorHeader, errorBody);
+                case HttpURLConnection.HTTP_UNAUTHORIZED:
+                case HttpURLConnection.HTTP_PROXY_AUTH:
+                    // if we get here with HTTP_UNAUTHORIZED or HTTP_PROXY_AUTH the user canceled the
+                    // username/password dialog. Throw an OsmTransferCancelledException.
+                    //
+                    throw new OsmTransferCancelledException();
                 case HttpURLConnection.HTTP_CONFLICT:
                     if (ChangesetClosedException.errorHeaderMatchesPattern(errorHeader))
@@ -583,8 +600,10 @@
                 }
                 throw new OsmTransferException(e);
+            } catch(IOException e){
+                throw new OsmTransferException(e);
+            } catch(OsmTransferCancelledException e){
+                throw e;
             } catch(OsmTransferException e) {
                 throw e;
-            } catch (Exception e) {
-                throw new OsmTransferException(e);
             }
         }
Index: trunk/src/org/openstreetmap/josm/io/OsmConnection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmConnection.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/io/OsmConnection.java	(revision 2641)
@@ -2,11 +2,6 @@
 package org.openstreetmap.josm.io;
 
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Font;
-import java.awt.GridBagLayout;
-import java.net.Authenticator;
 import java.net.HttpURLConnection;
-import java.net.PasswordAuthentication;
+import java.net.Authenticator.RequestorType;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
@@ -16,14 +11,8 @@
 import java.util.logging.Logger;
 
-import javax.swing.JCheckBox;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JPasswordField;
-import javax.swing.JTextField;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.ExtendedDialog;
+import org.openstreetmap.josm.io.auth.CredentialsManagerException;
+import org.openstreetmap.josm.io.auth.CredentialsManagerFactory;
+import org.openstreetmap.josm.io.auth.CredentialsManagerResponse;
 import org.openstreetmap.josm.tools.Base64;
-import org.openstreetmap.josm.tools.GBC;
 
 /**
@@ -38,14 +27,4 @@
     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();
 
     /**
@@ -53,44 +32,9 @@
      */
     static {
-        // TODO: current authentication handling is sub-optimal in that it seems to use the same authenticator for
-        // any kind of request. HTTP requests executed by plugins, e.g. to password-protected WMS servers,
-        // will use the same username/password which is undesirable.
         try {
             HttpURLConnection.setFollowRedirects(true);
-            Authenticator.setDefault(authentication);
         } catch (SecurityException e) {
+            e.printStackTrace();
         }
-    }
-
-    /**
-     * The authentication class handling the login requests.
-     */
-    public static class OsmAuth extends Authenticator {
-        /**
-         * Set to true, when the autenticator tried the password once.
-         */
-        public boolean passwordtried = false;
-        /**
-         * Whether the user cancelled the password dialog
-         */
-        public boolean authCancelled = false;
-        @Override protected PasswordAuthentication getPasswordAuthentication() {
-            return credentialsManager.getPasswordAuthentication(this);
-        }
-    }
-
-    /**
-     * 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;
     }
 
@@ -115,17 +59,31 @@
     }
 
-    protected void addAuth(HttpURLConnection con) throws CharacterCodingException {
+    protected void addAuth(HttpURLConnection con) throws OsmTransferException {
         CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
-        String auth;
+        CredentialsManagerResponse response;
+        String token;
         try {
-            synchronized (credentialsManager) {
-                auth = credentialsManager.lookup(CredentialsManager.Key.USERNAME) + ":" +
-                credentialsManager.lookup(CredentialsManager.Key.PASSWORD);
+            synchronized (CredentialsManagerFactory.getCredentialManager()) {
+                response = CredentialsManagerFactory.getCredentialManager().getCredentials(RequestorType.SERVER, false /* don't know yet whether the credentials will succeed */);
             }
-        } catch (CredentialsManager.CMException e) {
-            auth = ":";
+        } catch (CredentialsManagerException e) {
+            throw new OsmTransferException(e);
         }
-        ByteBuffer bytes = encoder.encode(CharBuffer.wrap(auth));
-        con.addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));
+        if (response == null) {
+            token = ":";
+        } else if (response.isCanceled()) {
+            cancel = true;
+            return;
+        } else {
+            String username= response.getUsername() == null ? "" : response.getUsername();
+            String password = response.getPassword() == null ? "" : String.valueOf(response.getPassword());
+            token = username + ":" + password;
+            try {
+                ByteBuffer bytes = encoder.encode(CharBuffer.wrap(token));
+                con.addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));
+            } catch(CharacterCodingException e) {
+                throw new OsmTransferException(e);
+            }
+        }
     }
 
@@ -139,146 +97,3 @@
         return cancel;
     }
-    /**
-     * Default implementation of the CredentialsManager interface.
-     * Saves passwords in plain text file.
-     */
-    public static class PlainCredentialsManager implements CredentialsManager {
-        public String lookup(CredentialsManager.Key key) throws CMException {
-            String secret = Main.pref.get("osm-server." + key.toString(), null);
-            if (secret == null) throw new CredentialsManager.NoContentException();
-            return secret;
-        }
-        public void store(CredentialsManager.Key key, String secret) {
-            Main.pref.put("osm-server." + key.toString(), secret);
-        }
-        public PasswordAuthentication getPasswordAuthentication(OsmAuth caller) {
-            String username, password;
-            try {
-                username = lookup(Key.USERNAME);
-            } catch (CMException e) {
-                username = "";
-            }
-            try {
-                password = lookup(Key.PASSWORD);
-            } 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());
-                }
-                p.add(new JLabel(tr("Username")), GBC.std().insets(0,0,10,0));
-                JTextField usernameField = new JTextField(username, 20);
-                p.add(usernameField, GBC.eol());
-                p.add(new JLabel(tr("Password")), GBC.std().insets(0,0,10,0));
-                JPasswordField passwordField = new JPasswordField(password, 20);
-                p.add(passwordField, GBC.eol());
-                JLabel warning = new JLabel(tr("Warning: The password is transferred unencrypted."));
-                warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
-                p.add(warning, GBC.eop());
-
-                JCheckBox savePassword = new JCheckBox(tr("Save user and password (unencrypted)"),
-                        !username.equals("") && !password.equals(""));
-                p.add(savePassword, GBC.eop());
-
-                ExtendedDialog dialog = new ExtendedDialog(
-                        Main.parent,
-                        tr("Enter Password"),
-                        new String[] {tr("Login"), tr("Cancel")}
-                );
-                dialog.setContent(p);
-                dialog.setButtonIcons( new String[] {"ok.png", "cancel.png"});
-                dialog.showDialog();
-
-                if (dialog.getValue() != 1) {
-                    caller.authCancelled = true;
-                    return null;
-                }
-                username = usernameField.getText();
-                password = String.valueOf(passwordField.getPassword());
-                if (savePassword.isSelected()) {
-                    store(Key.USERNAME, username);
-                    store(Key.PASSWORD, password);
-                }
-                if (username.equals(""))
-                    return null;
-            }
-            caller.passwordtried = true;
-            return new PasswordAuthentication(username, password.toCharArray());
-        }
-        public PreferenceAdditions newPreferenceAdditions() {
-            return new PreferenceAdditions() {
-                /**
-                 * Editfield for the Base url to the REST API from OSM.
-                 */
-                final private JTextField osmDataServerURL = new JTextField(20);
-                /**
-                 * Editfield for the username to the OSM account.
-                 */
-                final private JTextField osmDataUsername = new JTextField(20);
-                /**
-                 * Passwordfield for the userpassword of the REST API.
-                 */
-                final private JPasswordField osmDataPassword = new JPasswordField(20);
-
-                private String oldServerURL = "";
-                private String oldUsername = "";
-                private String oldPassword = "";
-
-                public void addPreferenceOptions(JPanel panel) {
-                    try {
-                        oldServerURL = lookup(Key.OSM_SERVER_URL); // result is not null (see CredentialsManager)
-                    } catch (CMException e) {
-                        oldServerURL = "";
-                    }
-                    if (oldServerURL.equals("")) {
-                        oldServerURL = "http://api.openstreetmap.org/api";
-                    }
-                    try {
-                        oldUsername = lookup(Key.USERNAME);
-                    } catch (CMException e) {
-                        oldUsername = "";
-                    }
-                    try {
-                        oldPassword = lookup(Key.PASSWORD);
-                    } catch (CMException e) {
-                        oldPassword = "";
-                    }
-                    osmDataServerURL.setText(oldServerURL);
-                    osmDataUsername.setText(oldUsername);
-                    osmDataPassword.setText(oldPassword);
-                    osmDataServerURL.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."));
-                    panel.add(new JLabel(tr("Base Server URL")), GBC.std());
-                    panel.add(osmDataServerURL, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
-                    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 newServerURL = osmDataServerURL.getText();
-                    String newUsername = osmDataUsername.getText();
-                    String newPassword = String.valueOf(osmDataPassword.getPassword());
-                    if (!oldServerURL.equals(newServerURL)) {
-                        store(Key.OSM_SERVER_URL, newServerURL);
-                    }
-                    if (!oldUsername.equals(newUsername)) {
-                        store(Key.USERNAME, newUsername);
-                    }
-                    if (!oldPassword.equals(newPassword)) {
-                        store(Key.PASSWORD, newPassword);
-                    }
-                }
-            };
-        }
-    }
 }
Index: trunk/src/org/openstreetmap/josm/io/OsmServerReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 2638)
+++ trunk/src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 2641)
@@ -10,5 +10,5 @@
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.nio.charset.CharacterCodingException;
+import java.util.logging.Logger;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.Inflater;
@@ -29,5 +29,5 @@
  */
 public abstract class OsmServerReader extends OsmConnection {
-
+    static private final Logger logger = Logger.getLogger(OsmServerReader.class.getName());
     private OsmApi api = OsmApi.getOsmApi();
     private boolean doAuthenticate = false;
@@ -68,12 +68,9 @@
             }
 
-            try {
-                if (doAuthenticate) {
-                    addAuth(activeConnection);
-                }
-            } catch(CharacterCodingException e) {
-                System.err.println(tr("Error: failed to add authentication credentials to the connection."));
-                throw new OsmTransferException(e);
+            if (doAuthenticate) {
+                addAuth(activeConnection);
             }
+            if (cancel)
+                throw new OsmTransferCancelledException();
             if (Main.pref.getBoolean("osm-server.use-compression", true)) {
                 activeConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");
@@ -86,9 +83,13 @@
                 activeConnection.connect();
             } catch (Exception e) {
+                e.printStackTrace();
                 throw new OsmTransferException(tr("Couldn't connect to the OSM server. Please check your internet connection."), e);
             }
             try {
-                if (isAuthCancelled() && activeConnection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED)
+                if (activeConnection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED)
                     throw new OsmApiException(HttpURLConnection.HTTP_UNAUTHORIZED,null,null);
+
+                if (activeConnection.getResponseCode() == HttpURLConnection.HTTP_PROXY_AUTH)
+                    throw new OsmTransferCancelledException();
 
                 if (activeConnection.getResponseCode() != HttpURLConnection.HTTP_OK) {
Index: trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java	(revision 2641)
+++ trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java	(revision 2641)
@@ -0,0 +1,48 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.auth;
+
+import java.net.PasswordAuthentication;
+import java.net.Authenticator.RequestorType;
+
+/**
+ * A CredentialManager manages two credentials:
+ * <ul>
+ *   <li>the credential for {@see RequestorType#SERVER} which is equal to the OSM API credentials
+ *   in JOSM</li>
+ *   <li>the credential for {@see RequestorType#PROXY} which is equal to the credentials for an
+ *   optional HTTP proxy server a user may use</li>
+ *  </ul>
+ */
+public interface CredentialsManager {
+
+    /**
+     * Looks up the credentials for a given type.
+     * 
+     * @param the type of service. {@see RequestorType#SERVER} for the OSM API server, {@see RequestorType#PROXY}
+     * for a proxy server
+     * @return the credentials
+     * @throws CredentialsManagerException thrown if a problem occurs in a implementation of this interface
+     */
+    public PasswordAuthentication lookup(RequestorType requestorType) throws CredentialsManagerException;
+
+    /**
+     * Saves the credentials in <code>credentials</code> for the given service type.
+     * 
+     * @param the type of service. {@see RequestorType#SERVER} for the OSM API server, {@see RequestorType#PROXY}
+     * for a proxy server
+     * @param credentials the credentials
+     * @throws CredentialsManagerException thrown if a problem occurs in a implementation of this interface
+     */
+    public void store(RequestorType requestorType, PasswordAuthentication credentials) throws CredentialsManagerException;
+
+    /**
+     * 
+     * @param requestorType  the type of service. {@see RequestorType#SERVER} for the OSM API server, {@see RequestorType#PROXY}
+     * for a proxy server
+     * @param noSuccessWithLastResponse true, if the last request with the supplied credentials failed; false otherwise.
+     * If true, implementations of this interface are adviced prompt user for new credentials.
+     * @throws CredentialsManagerException thrown if a problem occurs in a implementation of this interface
+
+     */
+    public CredentialsManagerResponse getCredentials(RequestorType requestorType, boolean noSuccessWithLastResponse) throws CredentialsManagerException;
+}
Index: trunk/src/org/openstreetmap/josm/io/auth/CredentialsManagerException.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/auth/CredentialsManagerException.java	(revision 2641)
+++ trunk/src/org/openstreetmap/josm/io/auth/CredentialsManagerException.java	(revision 2641)
@@ -0,0 +1,10 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.auth;
+
+public class CredentialsManagerException extends Exception {
+    public CredentialsManagerException() {super();}
+    public CredentialsManagerException(String message, Throwable cause) {super(message, cause);}
+    public CredentialsManagerException(String message) {super(message);}
+    public CredentialsManagerException(Throwable cause) {super(cause);}
+
+}
Index: trunk/src/org/openstreetmap/josm/io/auth/CredentialsManagerFactory.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/auth/CredentialsManagerFactory.java	(revision 2641)
+++ trunk/src/org/openstreetmap/josm/io/auth/CredentialsManagerFactory.java	(revision 2641)
@@ -0,0 +1,23 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.auth;
+
+/**
+ * CredentialManagerFactory is a factory for the single credential manager used.
+ * 
+ * Currently, it defaults to replying an instance of {@see JosmPreferencesCredentialManager}.
+ * 
+ */
+public class CredentialsManagerFactory {
+    private static CredentialsManager instance;
+
+    /**
+     * Replies the single credential manager used in JOSM
+     * 
+     * @return the single credential manager used in JOSM
+     */
+    static public CredentialsManager getCredentialManager() {
+        if (instance == null)
+            return new JosmPreferencesCredentialManager();
+        return instance;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/auth/CredentialsManagerResponse.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/auth/CredentialsManagerResponse.java	(revision 2641)
+++ trunk/src/org/openstreetmap/josm/io/auth/CredentialsManagerResponse.java	(revision 2641)
@@ -0,0 +1,34 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.auth;
+
+/**
+ * CredentialsManagerResponse represents the response from {@see CredentialsManager#getCredentials(java.net.Authenticator.RequestorType, boolean)}.
+ * 
+ * The response consists of the username and the password the requested credentials consists of.
+ * In addition, it provides information whether authentication was canceled by the user, i.e.
+ * because he or she canceled a username/password dialog (see {@see #isCanceled()}.
+ * 
+ */
+public class CredentialsManagerResponse {
+    private String username;
+    private char[] password;
+    private boolean canceled;
+    public String getUsername() {
+        return username;
+    }
+    public void setUsername(String username) {
+        this.username = username;
+    }
+    public char[] getPassword() {
+        return password;
+    }
+    public void setPassword(char[] password) {
+        this.password = password;
+    }
+    public boolean isCanceled() {
+        return canceled;
+    }
+    public void setCanceled(boolean cancelled) {
+        this.canceled = cancelled;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/auth/DefaultAuthenticator.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/auth/DefaultAuthenticator.java	(revision 2641)
+++ trunk/src/org/openstreetmap/josm/io/auth/DefaultAuthenticator.java	(revision 2641)
@@ -0,0 +1,48 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.auth;
+
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+/**
+ * This is the default authenticator used in JOSM. It delegates lookup of credentials
+ * for the OSM API and an optional proxy server to the currently configured
+ * {@see CredentialsManager}.
+ * 
+ */
+public  class DefaultAuthenticator extends Authenticator {
+    private static final Logger logger = Logger.getLogger(DefaultAuthenticator.class.getName());
+
+    private CredentialsManager credentialManager;
+    private final Map<RequestorType, Boolean> credentialsTried = new HashMap<RequestorType, Boolean>();
+
+    /**
+     * 
+     * @param credentialManager the credential manager
+     */
+    public DefaultAuthenticator(CredentialsManager credentialManager) {
+        this.credentialManager = credentialManager;
+    }
+
+    /**
+     * Called by the Java http stack when either the OSM API server or a proxy requires
+     * authentication.
+     * 
+     */
+    @Override protected PasswordAuthentication getPasswordAuthentication() {
+        try {
+            boolean tried = credentialsTried.get(getRequestorType()) != null;
+            CredentialsManagerResponse response = credentialManager.getCredentials(getRequestorType(), tried);
+            if (response == null || response.isCanceled())
+                return null;
+            credentialsTried.put(getRequestorType(), true);
+            return new PasswordAuthentication(response.getUsername(), response.getPassword());
+        } catch(CredentialsManagerException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialManager.java	(revision 2641)
+++ trunk/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialManager.java	(revision 2641)
@@ -0,0 +1,106 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.auth;
+
+import java.net.PasswordAuthentication;
+import java.net.Authenticator.RequestorType;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.io.CredentialDialog;
+import org.openstreetmap.josm.gui.preferences.ProxyPreferences;
+
+/**
+ * This is the default credential manager in JOSM. It keeps username and password for both
+ * the OSM API and an optional HTTP proxy in the JOSM preferences file.
+ *
+ */
+public class JosmPreferencesCredentialManager implements CredentialsManager {
+
+    /**
+     * @see CredentialsManager#lookup(RequestorType)
+     */
+    public PasswordAuthentication lookup(RequestorType requestorType) throws CredentialsManagerException{
+        if (requestorType == null)
+            return null;
+        String user;
+        String password;
+        switch(requestorType) {
+        case SERVER:
+            user = Main.pref.get("osm-server.username", null);
+            password = Main.pref.get("osm-server.password", null);
+            if (user == null)
+                return null;
+            return new PasswordAuthentication(user, password == null ? null : password.toCharArray());
+        case PROXY:
+            user = Main.pref.get(ProxyPreferences.PROXY_USER, null);
+            password = Main.pref.get(ProxyPreferences.PROXY_PASS, null);
+            if (user == null)
+                return null;
+            return new PasswordAuthentication(user, password == null ? null : password.toCharArray());
+        }
+        return null;
+    }
+
+    /**
+     * @see CredentialsManager#store(RequestorType, PasswordAuthentication)
+     */
+    public void store(RequestorType requestorType, PasswordAuthentication credentials) throws CredentialsManagerException {
+        if (requestorType == null)
+            return;
+        switch(requestorType) {
+        case SERVER:
+            Main.pref.put("osm-server.username", credentials.getUserName());
+            if (credentials.getPassword() == null) {
+                Main.pref.put("osm-server.password", null);
+            } else {
+                Main.pref.put("osm-server.password", String.valueOf(credentials.getPassword()));
+            }
+            break;
+        case PROXY:
+            Main.pref.put("proxy.username", credentials.getUserName());
+            if (credentials.getPassword() == null) {
+                Main.pref.put("proxy.password", null);
+            } else {
+                Main.pref.put("proxy.password", String.valueOf(credentials.getPassword()));
+            }
+            break;
+        }
+    }
+
+    /**
+     * @see CredentialsManager#getCredentials(RequestorType, boolean)
+     */
+    public CredentialsManagerResponse getCredentials(RequestorType requestorType, boolean noSuccessWithLastResponse) throws CredentialsManagerException{
+        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());
+
+        CredentialsManagerResponse response = new CredentialsManagerResponse();
+
+        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()
+                ));
+            }
+        } else {
+            response.setUsername(username);
+            response.setPassword(password.toCharArray());
+            response.setCanceled(false);
+        }
+        return response;
+    }
+}
