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