Ticket #2710: initial_multiuser_rework_v3.patch

File initial_multiuser_rework_v3.patch, 56.1 KB (added by taylor.smock, 5 years ago)

Partially working preferences panel -- still needs a lot of work

  • src/org/openstreetmap/josm/data/UserIdentityManager.java

     
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    66import java.text.MessageFormat;
     7import java.util.ArrayList;
     8import java.util.LinkedHashMap;
     9import java.util.List;
     10import java.util.Map;
     11import java.util.TreeMap;
    712
    813import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
    914import org.openstreetmap.josm.data.osm.User;
     
    1419import org.openstreetmap.josm.io.OsmApi;
    1520import org.openstreetmap.josm.io.OsmServerUserInfoReader;
    1621import org.openstreetmap.josm.io.OsmTransferException;
     22import org.openstreetmap.josm.io.auth.CredentialsAgentResponse;
    1723import org.openstreetmap.josm.io.auth.CredentialsManager;
    1824import org.openstreetmap.josm.spi.preferences.Config;
    1925import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
     
    7884                instance.initFromPreferences();
    7985            }
    8086            Config.getPref().addPreferenceChangeListener(instance);
     87            instance.populateAllUsers();
    8188        }
    8289        return instance;
    8390    }
    8491
    85     private String userName;
    86     private UserInfo userInfo;
    8792    private boolean accessTokenKeyChanged;
    8893    private boolean accessTokenSecretChanged;
    8994
     95    private String userName;
     96    private UserInfo userInfo;
     97    private LinkedHashMap<String, UserInfo> users;
     98
    9099    private UserIdentityManager() {
     100        users = new LinkedHashMap<>();
    91101    }
    92102
    93103    /**
     
    112122        if (trimmedUserName.isEmpty())
    113123            throw new IllegalArgumentException(
    114124                    MessageFormat.format("Expected non-empty value for parameter ''{0}'', got ''{1}''", "userName", userName));
    115         this.userName = trimmedUserName;
     125        userName = trimmedUserName;
    116126        userInfo = null;
    117127    }
    118128
     
    132142        if (trimmedUserName.isEmpty())
    133143            throw new IllegalArgumentException(tr("Expected non-empty value for parameter ''{0}'', got ''{1}''", "userName", userName));
    134144        CheckParameterUtil.ensureParameterNotNull(userInfo, "userInfo");
    135         this.userName = trimmedUserName;
     145        userName = trimmedUserName;
    136146        this.userInfo = userInfo;
    137147    }
    138148
     
    238248    }
    239249
    240250    /**
     251     * Initializes the user identity manager from OAuth request of user details.
     252     * @param oauth The {@code OAuthAccessTokenHolder} with the key and secret
     253     * @see #initFromPreferences
     254     * @since xxx
     255     */
     256    public void initFromOauth(OAuthAccessTokenHolder oauth) {
     257        try {
     258            OsmServerUserInfoReader osmServerReader = new OsmServerUserInfoReader();
     259            UserInfo info = osmServerReader.fetchUserInfo(NullProgressMonitor.INSTANCE, oauth);
     260            setFullyIdentified(info.getDisplayName(), info);
     261        } catch (IllegalArgumentException | OsmTransferException e) {
     262            Logging.error(e);
     263        }
     264    }
     265
     266    private List<Map<String, String>> getDefaultOAuthList() {
     267        Map<String, String> variables = new TreeMap<>();
     268        TreeMap<String, String> vars = new TreeMap<>();
     269        vars.put("url", "osm-server.url");
     270        vars.put("login", "oauth.access-token.key");
     271        vars.put("password", "oauth.access-token.secret");
     272        vars.put("login-token-url", "oauth.settings.authorise-token-url");
     273        vars.put("auth-url", "oauth.settings.authorise-url");
     274        vars.put("consumer-key", "oauth.settings.consumer-key");
     275        vars.put("consumer-secret", "oauth.settings.consumer-secret");
     276        vars.put("login-url", "oauth.settings.osm-login-url");
     277        vars.put("logout-url", "oauth.settings.osm-logout-url");
     278        variables.put("auth-type", "oauth");
     279
     280        vars.forEach((key, value) -> variables.put(key, Config.getPref().get(value)));
     281        List<Map<String, String>> rList = new ArrayList<>();
     282        rList.add(variables);
     283        return rList;
     284    }
     285
     286    private List<Map<String, String>> getDefaultBasicAuthList() {
     287        Map<String, String> variables = new TreeMap<>();
     288        TreeMap<String, String> vars = new TreeMap<>();
     289
     290        vars.put("url", "osm-server-url");
     291        vars.put("login", "osm-server.username");
     292        vars.put("password", "osm-server.password");
     293
     294        variables.put("auth-type", "basic");
     295        vars.forEach((key, value) -> variables.put(key, Config.getPref().get(value)));
     296        List<Map<String, String>> rList = new ArrayList<>();
     297        return rList;
     298    }
     299
     300    private List<Map<String, String>> getDefaultAuthList() {
     301        List<Map<String, String>> rMap = getDefaultOAuthList();
     302        rMap.addAll(getDefaultBasicAuthList());
     303        return rMap;
     304    }
     305
     306    /**
     307     * Populate the users
     308     * @since xxx
     309     */
     310    public void populateAllUsers() {
     311        List<Map<String, String>> authList = Config.getPref().getListOfMaps("all-authorizations", getDefaultAuthList());
     312        for (Map<String, String> map : authList) { // TODO fix
     313            if ("oauth".equals(map.get("auth-type"))) {
     314                OAuthAccessTokenHolder oauth = new OAuthAccessTokenHolder();
     315                oauth.setAccessToken(map.get("login"), map.get("password"));
     316                oauth.setOsmApi(map.get("url"));
     317                instance.initFromOauth(oauth);
     318                users.put(getUserName(), getUserInfo());
     319            } else if ("basic".equals(map.get("auth-type"))) {
     320                CredentialsAgentResponse response = new CredentialsAgentResponse();
     321                response.setUsername(map.get("login"));
     322                response.setPassword(map.get("password").toCharArray());
     323            }
     324        }
     325
     326        if (OsmApi.isUsingOAuth() && OAuthAccessTokenHolder.getInstance().containsAccessToken() &&
     327                !NetworkManager.isOffline(OnlineResource.OSM_API)) {
     328            try {
     329                instance.initFromOAuth();
     330            } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {
     331                Logging.error(e);
     332                // Fall back to preferences if OAuth identification fails for any reason
     333                instance.initFromPreferences();
     334            }
     335        } else {
     336            instance.initFromPreferences();
     337        }
     338    }
     339
     340    /**
    241341     * Replies true if the user with name <code>username</code> is the current user
    242342     *
    243343     * @param userName the user name
     
    264364        }
    265365    }
    266366
     367    /**
     368     * Get all information on all users that have logged in to JOSM
     369     * @return A {@code HashMap} with username/UserInfo pairs.
     370     * @since xxx
     371     */
     372    public Map<String, UserInfo> getAllUserInformation() {
     373        if (users == null) {
     374            populateAllUsers();
     375        }
     376        return users;
     377    }
     378
     379    /**
     380     * Get user authentication information
     381     * @return The user information (passwords are protected)
     382     * @since xxx
     383     */
     384    public List<Map<String, String>> getUserAuthInformation() {
     385        List<Map<String, String>> authList = Config.getPref().getListOfMaps("all-authorizations", getDefaultAuthList());
     386        for (Map<String, String> map : authList) {
     387            if ("basic".equals(map.get("auth-type"))) {
     388                // TODO protect passwords, even though they are stored in plain text
     389                // map.put("password", "PROTECTED");
     390            }
     391        }
     392        return authList;
     393    }
     394
     395    /**
     396     * Save authentication information
     397     * @param users To save (any user NOT in this map WILL be deleted)
     398     */
     399    public void saveUserAuthInformation(List<Map<String, String>> users) {
     400        Config.getPref().putListOfMaps("all-authorizations", users);
     401    }
     402
    267403    /* ------------------------------------------------------------------- */
    268404    /* interface PreferenceChangeListener                                  */
    269405    /* ------------------------------------------------------------------- */
  • src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java

     
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.util.List;
     7import java.util.Map;
     8import java.util.TreeMap;
     9
     10import org.openstreetmap.josm.data.UserIdentityManager;
     11import org.openstreetmap.josm.io.OsmApi;
    612import org.openstreetmap.josm.io.auth.CredentialsAgent;
    713import org.openstreetmap.josm.io.auth.CredentialsAgentException;
    814import org.openstreetmap.josm.spi.preferences.Config;
     
    1622public class OAuthAccessTokenHolder {
    1723    private static OAuthAccessTokenHolder instance;
    1824
     25    private OsmApi osmApi = OsmApi.getOsmApi();
     26
    1927    /**
    2028     * Replies the unique instance.
    2129     * @return The unique instance of {@code OAuthAccessTokenHolder}
     
    183191            Logging.warn(tr("Failed to store OAuth Access Token to credentials manager"));
    184192            Logging.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
    185193        }
     194        List<Map<String, String>> users = UserIdentityManager.getInstance().getUserAuthInformation();
     195        boolean present = false;
     196        for (Map<String, String> user : users) {
     197            if ("oauth".equals(user.get("auth-type")) && accessTokenKey.equals(user.get("auth-type"))) {
     198                user.put("password", accessTokenSecret);
     199                user.put("url", osmApi.getHost());
     200                present = true;
     201                break;
     202            }
     203        }
     204        if (!present) {
     205            Map<String, String> map = new TreeMap<>();
     206            map.put("login", accessTokenKey);
     207            map.put("password", accessTokenSecret);
     208            map.put("url", osmApi.getHost());
     209        }
    186210    }
    187211
    188212    /**
     213     * Set the API to use with the user
     214     * @param serverUrl The URL for the OSM server
     215     * @since xxx
     216     */
     217    public void setOsmApi(String serverUrl) {
     218        osmApi = OsmApi.getOsmApi(serverUrl);
     219    }
     220
     221    /**
     222     * Get the osmApi for use with this oauth object
     223     * @return The OsmApi to use
     224     */
     225    public OsmApi getOsmApi() {
     226        return osmApi;
     227    }
     228
     229    /**
    189230     * Clears the content of this holder
    190231     */
    191232    public void clear() {
  • src/org/openstreetmap/josm/gui/io/UploadParameterSummaryPanel.java

     
    55import static org.openstreetmap.josm.tools.I18n.trn;
    66
    77import java.awt.BorderLayout;
     8import java.awt.event.ItemEvent;
     9import java.awt.event.ItemListener;
    810import java.beans.PropertyChangeEvent;
    911import java.beans.PropertyChangeListener;
     12import java.util.Map;
    1013import java.util.Optional;
    1114
    1215import javax.swing.BorderFactory;
     16import javax.swing.DefaultComboBoxModel;
     17import javax.swing.JComboBox;
    1318import javax.swing.JLabel;
    1419import javax.swing.JPanel;
    1520import javax.swing.event.HyperlinkEvent;
    1621import javax.swing.event.HyperlinkListener;
    1722
     23import org.openstreetmap.josm.data.UserIdentityManager;
    1824import org.openstreetmap.josm.data.osm.Changeset;
     25import org.openstreetmap.josm.data.osm.UserInfo;
    1926import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
    2027import org.openstreetmap.josm.io.Capabilities;
    2128import org.openstreetmap.josm.io.OsmApi;
     
    2229import org.openstreetmap.josm.io.UploadStrategySpecification;
    2330import org.openstreetmap.josm.spi.preferences.Config;
    2431import org.openstreetmap.josm.tools.ImageProvider;
     32import org.openstreetmap.josm.tools.Logging;
    2533
    2634/**
    2735 * A panel that displays a summary of data the user is about to upload
     
    114122        return msg;
    115123    }
    116124
     125    protected JComboBox<String> buildPossibleUserBox() {
     126        DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
     127        Map<String, UserInfo> info = UserIdentityManager.getInstance().getAllUserInformation();
     128        info.forEach((userName, userInfo) -> model.addElement(userName));
     129        JComboBox<String> rBox = new JComboBox<>(model);
     130        UserInfo user = UserIdentityManager.getInstance().getUserInfo();
     131        String userName = user.getDisplayName() != null ? user.getDisplayName() : tr("Please login");
     132        if (model.getIndexOf(userName) < 0) model.addElement(userName);
     133        model.setSelectedItem(userName);
     134        rBox.addItemListener(new ItemListener() {
     135            @Override
     136            public void itemStateChanged(ItemEvent e) {
     137                if (e.getStateChange() == ItemEvent.SELECTED) {
     138                    Logging.info("{0} was selected, switching to {1}", userName, e.getItem());
     139                    model.setSelectedItem(e.getItem());
     140                }
     141            }
     142        });
     143        return rBox;
     144    }
     145
    117146    protected void build() {
    118147        jepMessage = new JMultilineLabel("");
    119148        jepMessage.addHyperlinkListener(this);
     
    128157        JPanel pnl = new JPanel(new BorderLayout());
    129158        pnl.add(lblWarning, BorderLayout.NORTH);
    130159        add(pnl, BorderLayout.WEST);
     160        JComboBox<String> options = buildPossibleUserBox();
     161        if (options.getItemCount() > 1) add(buildPossibleUserBox(), BorderLayout.SOUTH);
    131162    }
    132163
    133164    public void setConfigurationParameterRequestListener(ConfigurationParameterRequestHandler handler) {
  • src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java

     
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import java.awt.BorderLayout;
    7 import java.awt.GridBagConstraints;
     6import java.awt.Component;
     7import java.awt.Dimension;
    88import java.awt.GridBagLayout;
    9 import java.awt.Insets;
    10 import java.awt.event.ItemEvent;
    11 import java.awt.event.ItemListener;
     9import java.awt.event.ActionEvent;
    1210import java.beans.PropertyChangeEvent;
    1311import java.beans.PropertyChangeListener;
     12import java.util.ArrayList;
     13import java.util.List;
     14import java.util.Map;
    1415
    15 import javax.swing.ButtonGroup;
     16import javax.swing.AbstractAction;
     17import javax.swing.JButton;
    1618import javax.swing.JPanel;
    17 import javax.swing.JRadioButton;
    1819import javax.swing.JSeparator;
    1920
    20 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
     21import org.openstreetmap.josm.data.UserIdentityManager;
    2122import org.openstreetmap.josm.gui.help.HelpUtil;
    2223import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
    2324import org.openstreetmap.josm.io.OsmApi;
    24 import org.openstreetmap.josm.io.auth.CredentialsManager;
    2525import org.openstreetmap.josm.spi.preferences.Config;
     26import org.openstreetmap.josm.tools.GBC;
    2627import org.openstreetmap.josm.tools.Logging;
    2728
    2829/**
     
    3132 */
    3233public class AuthenticationPreferencesPanel extends VerticallyScrollablePanel implements PropertyChangeListener {
    3334
    34     /** indicates whether we use basic authentication */
    35     private final JRadioButton rbBasicAuthentication = new JRadioButton();
    36     /** indicates whether we use OAuth as authentication scheme */
    37     private final JRadioButton rbOAuth = new JRadioButton();
     35    /** add a basic authentication method */
     36    private final JButton rbBasicAuthentication = new JButton(tr("Add Basic Authentication"));
     37    /** add a OAuth method */
     38    private final JButton rbOAuth = new JButton(tr("Add OAuth"));
    3839    /** the panel which contains the authentication parameters for the respective authentication scheme */
    39     private final JPanel pnlAuthenticationParameteters = new JPanel(new BorderLayout());
    40     /** the panel for the basic authentication parameters */
    41     private BasicAuthenticationPreferencesPanel pnlBasicAuthPreferences;
    42     /** the panel for the OAuth authentication parameters */
    43     private OAuthAuthenticationPreferencesPanel pnlOAuthPreferences;
     40    private final JPanel pnlAuthenticationParameteters = new JPanel();
     41    /** the panels for the basic authentication parameters */
     42    private List<BasicAuthenticationPreferencesPanel> pnlBasicAuthPreferences;
     43    /** the panels for the OAuth authentication parameters */
     44    private List<OAuthAuthenticationPreferencesPanel> pnlOAuthPreferences;
    4445    /** the panel for messages notifier preferences */
    4546    private FeaturesPanel pnlFeaturesPreferences;
    4647
     48    /** The authentication preference key */
     49    public static final String AUTH_TYPE_KEY = "auth-type";
     50    /** The value in {@code AUTH_TYPE_KEY}'s pref for OAuth */
     51    public static final String AUTH_OAUTH = "oauth";
     52    /** The value in {@code AUTH_TYPE_KEY}'s pref for basic authentication */
     53    public static final String AUTH_BASIC = "basic";
     54
    4755    /**
    4856     * Constructs a new {@code AuthenticationPreferencesPanel}.
    4957     */
     
    5866     */
    5967    protected final void build() {
    6068        setLayout(new GridBagLayout());
    61         GridBagConstraints gc = new GridBagConstraints();
    6269
    63         AuthenticationMethodChangeListener authChangeListener = new AuthenticationMethodChangeListener();
     70        //-- the panel for API feature preferences
     71        pnlFeaturesPreferences = new FeaturesPanel();
     72        add(pnlFeaturesPreferences, GBC.eol());
    6473
    6574        // -- radio button for basic authentication
    66         gc.anchor = GridBagConstraints.NORTHWEST;
    67         gc.fill = GridBagConstraints.HORIZONTAL;
    68         gc.gridx = 1;
    69         gc.weightx = 1.0;
    70         gc.insets = new Insets(0, 0, 0, 3);
    71         add(rbBasicAuthentication, gc);
    72         rbBasicAuthentication.setText(tr("Use Basic Authentication"));
    73         rbBasicAuthentication.setToolTipText(tr("Select to use HTTP basic authentication with your OSM username and password"));
    74         rbBasicAuthentication.addItemListener(authChangeListener);
     75        rbBasicAuthentication.setAction(new AbstractAction() {
     76            @Override
     77            public void actionPerformed(ActionEvent e) {
     78                BasicAuthenticationPreferencesPanel panel = new BasicAuthenticationPreferencesPanel();
     79                panel.initFromPreferences();
     80                if (isPresent(panel)) {
     81                    panel.setUserName("");
     82                }
     83                if (!isPresent(panel)) {
     84                    redrawAuthenticationPanel(panel);
     85                }
     86            }
     87        });
     88        rbBasicAuthentication.setText(tr("Add Basic Authentication"));
     89        rbBasicAuthentication.setToolTipText(tr("Select to add HTTP basic authentication with your OSM username and password"));
    7590
    7691        //-- radio button for OAuth
    77         gc.gridx = 0;
    78         gc.weightx = 0.0;
    79         add(rbOAuth, gc);
    80         rbOAuth.setText(tr("Use OAuth"));
    81         rbOAuth.setToolTipText(tr("Select to use OAuth as authentication mechanism"));
    82         rbOAuth.addItemListener(authChangeListener);
     92        rbOAuth.setAction(new AbstractAction() {
     93            @Override
     94            public void actionPerformed(ActionEvent e) {
     95                OAuthAuthenticationPreferencesPanel panel = new OAuthAuthenticationPreferencesPanel();
     96                panel.initFromPreferences();
     97                redrawAuthenticationPanel(panel);
     98            }
     99        });
     100        rbOAuth.setText(tr("Add OAuth"));
     101        rbOAuth.setToolTipText(tr("Select to add a OAuth authentication mechanism"));
    83102
    84         //-- radio button for OAuth
    85         ButtonGroup bg = new ButtonGroup();
    86         bg.add(rbBasicAuthentication);
    87         bg.add(rbOAuth);
     103        add(new JSeparator(), GBC.eol());
    88104
    89105        //-- add the panel which will hold the authentication parameters
    90         gc.gridx = 0;
    91         gc.gridy = 1;
    92         gc.gridwidth = 2;
    93         gc.fill = GridBagConstraints.BOTH;
    94         gc.weightx = 1.0;
    95         gc.weighty = 1.0;
    96         add(pnlAuthenticationParameteters, gc);
    97106
     107        add(pnlAuthenticationParameteters, GBC.eol());
     108        add(rbBasicAuthentication);
     109        add(rbOAuth, GBC.eol());
     110
    98111        //-- the two panels for authentication parameters
    99         pnlBasicAuthPreferences = new BasicAuthenticationPreferencesPanel();
    100         pnlOAuthPreferences = new OAuthAuthenticationPreferencesPanel();
     112        pnlBasicAuthPreferences = new ArrayList<>();
     113        pnlOAuthPreferences = new ArrayList<>();
    101114
    102         rbBasicAuthentication.setSelected(true);
    103         pnlAuthenticationParameteters.add(pnlBasicAuthPreferences, BorderLayout.CENTER);
     115        populateAuthPanels();
     116    }
    104117
    105         gc.gridy = 2;
    106         add(new JSeparator(), gc);
     118    private void populateAuthPanels() {
     119        List<Map<String, String>> users = UserIdentityManager.getInstance().getUserAuthInformation();
     120        for (Map<String, String> user : users) {
     121            if (AUTH_OAUTH.equals(user.get(AUTH_TYPE_KEY))) {
     122                OAuthAuthenticationPreferencesPanel panel = new OAuthAuthenticationPreferencesPanel();
     123                panel.initFromMap(user);
     124                redrawAuthenticationPanel(panel);
     125            } else if (AUTH_BASIC.equals(user.get(AUTH_TYPE_KEY))) {
     126                BasicAuthenticationPreferencesPanel panel = new BasicAuthenticationPreferencesPanel();
     127                panel.initFromMap(user);
     128                redrawAuthenticationPanel(panel);
     129            } else if (user.get(AUTH_TYPE_KEY) != null) {
     130                Logging.info("Unknown authentication type: {0}", user.get(AUTH_TYPE_KEY));
     131            } else {
     132                Logging.error("There was no authentication type");
     133            }
     134        }
     135    }
    107136
    108         //-- the panel for API feature preferences
    109         gc.gridy = 3;
    110         gc.fill = GridBagConstraints.NONE;
    111         pnlFeaturesPreferences = new FeaturesPanel();
    112         add(pnlFeaturesPreferences, gc);
     137    private void redrawAuthenticationPanel(JPanel panel) {
     138        if (panel == null) {
     139            recalculateAuthenticationParametersSize();
     140            pnlAuthenticationParameteters.revalidate();
     141            return;
     142        }
     143        List<Component> components = new ArrayList<>();
     144        JButton remove = new JButton(tr("Remove"));
     145        components.add(panel);
     146        components.add(new JSeparator());
     147        remove.setAction(new AbstractAction() {
     148            @Override
     149            public void actionPerformed(ActionEvent e) {
     150                for (Component component : components) {
     151                    if (pnlOAuthPreferences.contains(component)) {
     152                        pnlOAuthPreferences.remove(component);
     153                    }
     154                    if (pnlBasicAuthPreferences.contains(component)) {
     155                        pnlBasicAuthPreferences.remove(component);
     156                    }
     157                    pnlAuthenticationParameteters.remove(component);
     158                    redrawAuthenticationPanel(null);
     159                }
     160            }
     161        });
     162        remove.setText(tr("Remove"));
     163        components.add(remove);
     164        for (Component component : components) {
     165            pnlAuthenticationParameteters.add(component, GBC.eol());
     166        }
     167        if (panel instanceof BasicAuthenticationPreferencesPanel) {
     168            pnlBasicAuthPreferences.add((BasicAuthenticationPreferencesPanel) panel);
     169        } else if (panel instanceof OAuthAuthenticationPreferencesPanel) {
     170            pnlOAuthPreferences.add((OAuthAuthenticationPreferencesPanel) panel);
     171        }
     172        recalculateAuthenticationParametersSize();
     173        pnlAuthenticationParameteters.revalidate();
    113174    }
    114175
     176    private void recalculateAuthenticationParametersSize() {
     177        Dimension d = new Dimension();
     178        for (Component component : pnlAuthenticationParameteters.getComponents()) {
     179            Dimension dComponent = component.getPreferredSize();
     180            d.setSize(Math.max(d.getWidth(), dComponent.getWidth()), d.getHeight() + dComponent.getHeight());
     181        }
     182        pnlAuthenticationParameteters.setPreferredSize(d);
     183    }
     184
     185    private boolean isPresent(Component component) {
     186        List<Component> components = new ArrayList<>();
     187        for (Component tcomponent : pnlAuthenticationParameteters.getComponents()) {
     188            components.add(tcomponent);
     189        }
     190        if (component instanceof BasicAuthenticationPreferencesPanel) {
     191            BasicAuthenticationPreferencesPanel realComponent = (BasicAuthenticationPreferencesPanel) component;
     192            for (BasicAuthenticationPreferencesPanel check : pnlBasicAuthPreferences) {
     193                if (check.equals(realComponent)) return true;
     194            }
     195        } else if (component instanceof OAuthAuthenticationPreferencesPanel) {
     196            OAuthAuthenticationPreferencesPanel realComponent = (OAuthAuthenticationPreferencesPanel) component;
     197            for (OAuthAuthenticationPreferencesPanel check : pnlOAuthPreferences) {
     198                if (check.equals(realComponent)) return true;
     199            }
     200        }
     201        return false;
     202    }
     203
    115204    /**
    116205     * Initializes the panel from preferences
    117206     */
    118207    public final void initFromPreferences() {
    119208        final String authMethod = OsmApi.getAuthMethod();
    120         if ("basic".equals(authMethod)) {
     209        if (AUTH_BASIC.equals(authMethod)) {
    121210            rbBasicAuthentication.setSelected(true);
    122         } else if ("oauth".equals(authMethod)) {
     211        } else if (AUTH_OAUTH.equals(authMethod)) {
    123212            rbOAuth.setSelected(true);
    124213        } else {
    125214            Logging.warn(tr("Unsupported value in preference ''{0}'', got ''{1}''. Using authentication method ''Basic Authentication''.",
     
    126215                    "osm-server.auth-method", authMethod));
    127216            rbBasicAuthentication.setSelected(true);
    128217        }
    129         pnlBasicAuthPreferences.initFromPreferences();
    130         pnlOAuthPreferences.initFromPreferences();
     218        List<Map<String, String>> users = UserIdentityManager.getInstance().getUserAuthInformation();
     219        for (Map<String, String> user : users) {
     220            if (AUTH_OAUTH.equals(user.get(AUTH_TYPE_KEY))) {
     221                OAuthAuthenticationPreferencesPanel panel = new OAuthAuthenticationPreferencesPanel();
     222                panel.initFromMap(user);
     223                pnlOAuthPreferences.add(panel);
     224            } else if (AUTH_BASIC.equals(user.get(AUTH_TYPE_KEY))) {
     225                BasicAuthenticationPreferencesPanel panel = new BasicAuthenticationPreferencesPanel();
     226                panel.initFromMap(user);
     227                pnlBasicAuthPreferences.add(panel);
     228            }
     229        }
    131230        pnlFeaturesPreferences.initFromPreferences();
    132231    }
    133232
     
    137236    public final void saveToPreferences() {
    138237        // save the authentication method
    139238        String authMethod;
    140         if (rbBasicAuthentication.isSelected()) {
    141             authMethod = "basic";
     239        if (pnlOAuthPreferences.isEmpty()) {
     240            authMethod = AUTH_OAUTH;
    142241        } else {
    143             authMethod = "oauth";
     242            authMethod = AUTH_BASIC;
    144243        }
    145244        Config.getPref().put("osm-server.auth-method", authMethod);
    146         if ("basic".equals(authMethod)) {
    147             // save username and password and clear the OAuth token
    148             pnlBasicAuthPreferences.saveToPreferences();
    149             OAuthAccessTokenHolder.getInstance().clear();
    150             OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
    151         } else if ("oauth".equals(authMethod)) {
    152             // clear the password in the preferences
    153             pnlBasicAuthPreferences.clearPassword();
    154             pnlBasicAuthPreferences.saveToPreferences();
    155             pnlOAuthPreferences.saveToPreferences();
     245        for (BasicAuthenticationPreferencesPanel panel : pnlBasicAuthPreferences) {
     246            panel.saveToPreferences();
    156247        }
     248        for (OAuthAuthenticationPreferencesPanel panel : pnlOAuthPreferences) {
     249            panel.saveToPreferences();
     250        }
    157251        // save message notifications preferences. To be done after authentication preferences.
    158252        pnlFeaturesPreferences.saveToPreferences();
    159253    }
    160254
    161     /**
    162      * Listens to changes in the authentication method
    163      */
    164     class AuthenticationMethodChangeListener implements ItemListener {
    165         @Override
    166         public void itemStateChanged(ItemEvent e) {
    167             if (rbBasicAuthentication.isSelected()) {
    168                 pnlAuthenticationParameteters.removeAll();
    169                 pnlAuthenticationParameteters.add(pnlBasicAuthPreferences, BorderLayout.CENTER);
    170                 pnlBasicAuthPreferences.revalidate();
    171             } else {
    172                 pnlAuthenticationParameteters.removeAll();
    173                 pnlAuthenticationParameteters.add(pnlOAuthPreferences, BorderLayout.CENTER);
    174                 pnlOAuthPreferences.revalidate();
    175             }
    176             repaint();
    177         }
    178     }
    179 
    180255    @Override
    181256    public void propertyChange(PropertyChangeEvent evt) {
    182         if (pnlOAuthPreferences != null) {
    183             pnlOAuthPreferences.propertyChange(evt);
     257        /** TODO is this still necessary? */
     258        if (pnlOAuthPreferences != null && !pnlOAuthPreferences.isEmpty()) {
     259            for (OAuthAuthenticationPreferencesPanel panel : pnlOAuthPreferences) {
     260                panel.propertyChange(evt);
     261            }
    184262        }
    185263    }
    186264}
  • src/org/openstreetmap/josm/gui/preferences/server/BasicAuthenticationPreferencesPanel.java

     
    99import java.awt.Insets;
    1010import java.net.Authenticator.RequestorType;
    1111import java.net.PasswordAuthentication;
     12import java.util.Arrays;
     13import java.util.List;
     14import java.util.Map;
     15import java.util.TreeMap;
    1216
    1317import javax.swing.BorderFactory;
    1418import javax.swing.JLabel;
    1519import javax.swing.JPanel;
    1620
     21import org.openstreetmap.josm.data.UserIdentityManager;
    1722import org.openstreetmap.josm.gui.widgets.JosmPasswordField;
    1823import org.openstreetmap.josm.gui.widgets.JosmTextField;
    1924import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
     
    3338    private final JosmTextField tfOsmUserName = new JosmTextField();
    3439    /** the OSM password */
    3540    private final JosmPasswordField tfOsmPassword = new JosmPasswordField();
     41    /** The password key in the user map */
     42    public static final String KEY_PASSWORD = "password";
     43    /** The username key in the user map */
     44    public static final String KEY_USER = "login";
    3645    /** a panel with further information, e.g. some warnings */
    3746    private JPanel decorationPanel;
    3847
     
    93102     * Inits contents from preferences.
    94103     */
    95104    public void initFromPreferences() {
    96         CredentialsAgent cm = CredentialsManager.getInstance();
    97         try {
    98             decorationPanel.removeAll();
    99             decorationPanel.add(cm.getPreferencesDecorationPanel(), BorderLayout.CENTER);
    100             PasswordAuthentication pa = cm.lookup(RequestorType.SERVER, OsmApi.getOsmApi().getHost());
    101             if (pa == null) {
    102                 tfOsmUserName.setText("");
    103                 tfOsmPassword.setText("");
    104             } else {
    105                 tfOsmUserName.setText(pa.getUserName() == null ? "" : pa.getUserName());
    106                 tfOsmPassword.setText(pa.getPassword() == null ? "" : String.valueOf(pa.getPassword()));
     105        initFromMap(null);
     106    }
     107
     108    /**
     109     * Initializes contents from a map
     110     * @param user The map with the login/password
     111     */
     112    public void initFromMap(Map<String, String> user) {
     113        if (user == null) {
     114            user = new TreeMap<>();
     115            CredentialsAgent cm = CredentialsManager.getInstance();
     116            try {
     117                decorationPanel.removeAll();
     118                decorationPanel.add(cm.getPreferencesDecorationPanel(), BorderLayout.CENTER);
     119                PasswordAuthentication pa = cm.lookup(RequestorType.SERVER, OsmApi.getOsmApi().getHost());
     120                if (pa == null) {
     121                    user.put(KEY_USER, "");
     122                    user.put(KEY_PASSWORD, "");
     123                } else {
     124                    user.put("login", pa.getUserName() == null ? "" : pa.getUserName());
     125                    user.put("password", pa.getPassword() == null ? "" : String.valueOf(pa.getPassword()));
     126                }
     127            } catch (CredentialsAgentException e) {
     128                Logging.error(e);
     129                Logging.warn(tr("Failed to retrieve OSM credentials from credential manager."));
     130                Logging.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
     131                user.put(KEY_USER, "");
     132                user.put(KEY_PASSWORD, "");
    107133            }
    108         } catch (CredentialsAgentException e) {
    109             Logging.error(e);
    110             Logging.warn(tr("Failed to retrieve OSM credentials from credential manager."));
    111             Logging.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
    112             tfOsmUserName.setText("");
    113             tfOsmPassword.setText("");
    114134        }
     135
     136        tfOsmUserName.setText(user.get(KEY_USER) != null ? user.get(KEY_USER) : "");
     137        tfOsmPassword.setText(user.get(KEY_PASSWORD) != null ? user.get(KEY_PASSWORD) : "");
    115138    }
    116139
    117140    /**
     
    130153            Logging.warn(tr("Failed to save OSM credentials to credential manager."));
    131154            Logging.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
    132155        }
     156        List<Map<String, String>> users = UserIdentityManager.getInstance().getUserAuthInformation();
     157        boolean present = false;
     158        for (Map<String, String> user : users) {
     159            if (AuthenticationPreferencesPanel.AUTH_BASIC.equals(user.get(AuthenticationPreferencesPanel.AUTH_TYPE_KEY))
     160                    && tfOsmUserName.getText().trim().equals(user.get(KEY_USER))) {
     161                user.put(KEY_PASSWORD, Arrays.toString(tfOsmPassword.getPassword()));
     162                user.put("url", OsmApi.getOsmApi().getHost());
     163                present = true;
     164                break;
     165            }
     166        }
     167        if (!present) {
     168            Map<String, String> map = new TreeMap<>();
     169            map.put(KEY_USER, tfOsmUserName.getText().trim());
     170            map.put(KEY_PASSWORD, tfOsmPassword.getParent().toString());
     171            map.put("url", OsmApi.getOsmApi().getHost());
     172            users.add(map);
     173            UserIdentityManager.getInstance().saveUserAuthInformation(users);
     174        }
    133175    }
    134176
    135177    /**
     
    138180    public void clearPassword() {
    139181        tfOsmPassword.setText("");
    140182    }
     183
     184    @Override
     185    public boolean equals(Object obj) {
     186        if (!(obj instanceof BasicAuthenticationPreferencesPanel)) return false;
     187        BasicAuthenticationPreferencesPanel testPanel = (BasicAuthenticationPreferencesPanel) obj;
     188        if (testPanel.tfOsmUserName.getText().equals(tfOsmUserName.getText())) return true;
     189        return false;
     190    }
     191
     192    @Override
     193    public int hashCode() {
     194        return super.hashCode();
     195    }
     196
     197    /**
     198     * Get the username in the field
     199     * @return The username for this BasicAuthenticationPreference
     200     * @since xxx
     201     */
     202    public String getUserName() {
     203        return tfOsmUserName.getText();
     204    }
     205
     206    /**
     207     * Set the username in the field
     208     * @param userName for this BasicAuthenticationPreference
     209     * @since xxx
     210     */
     211    public void setUserName(String userName) {
     212        tfOsmUserName.setText(userName);
     213    }
    141214}
  • src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java

     
    1414import java.awt.event.ItemEvent;
    1515import java.beans.PropertyChangeEvent;
    1616import java.beans.PropertyChangeListener;
     17import java.util.Map;
     18import java.util.TreeMap;
    1719
    1820import javax.swing.AbstractAction;
    1921import javax.swing.BorderFactory;
     
    5153    private final JPanel pnlAuthorisationMessage = new JPanel(new BorderLayout());
    5254    private final NotYetAuthorisedPanel pnlNotYetAuthorised = new NotYetAuthorisedPanel();
    5355    private final AdvancedOAuthPropertiesPanel pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel();
    54     private final AlreadyAuthorisedPanel pnlAlreadyAuthorised = new AlreadyAuthorisedPanel();
     56    private final AlreadyAuthorisedPanel pnlAlreadyAuthorised = new AlreadyAuthorisedPanel(null);
    5557    private String apiUrl;
    5658
    5759    /**
     
    125127    }
    126128
    127129    protected void refreshView() {
     130        Map<String, String> map = new TreeMap<>();
     131        if (OAuthAccessTokenHolder.getInstance().containsAccessToken()) {
     132            map.put("login", OAuthAccessTokenHolder.getInstance().getAccessTokenKey());
     133            map.put("password", OAuthAccessTokenHolder.getInstance().getAccessTokenSecret());
     134        }
     135        refreshView(map);
     136    }
     137
     138    protected void refreshView(Map<String, String> user) {
    128139        pnlAuthorisationMessage.removeAll();
    129         if (OAuthAccessTokenHolder.getInstance().containsAccessToken()) {
     140        if (user.containsKey("login") && user.containsKey("password")) {
    130141            pnlAuthorisationMessage.add(pnlAlreadyAuthorised, BorderLayout.CENTER);
    131             pnlAlreadyAuthorised.refreshView();
     142            pnlAlreadyAuthorised.refreshView(user);
    132143            pnlAlreadyAuthorised.revalidate();
    133144        } else {
    134145            pnlAuthorisationMessage.add(pnlNotYetAuthorised, BorderLayout.CENTER);
     
    156167    }
    157168
    158169    /**
     170     * Initializes the panel from a map
     171     * @param user The map with a {@code login} and {@code password}.
     172     * Optional information includes {@code url}.
     173     */
     174    public void initFromMap(Map<String, String> user) {
     175        if (user.containsKey("url")) {
     176            setApiUrl(user.get("url").trim());
     177        } else {
     178            setApiUrl(OsmApi.getOsmApi().getServerUrl().trim());
     179        }
     180        refreshView(user);
     181    }
     182
     183    /**
    159184     * Saves the current values to preferences
    160185     */
    161186    public void saveToPreferences() {
     
    215240        private final JosmTextField tfAccessTokenSecret = new JosmTextField(null, null, 0, false);
    216241
    217242        /**
    218          * Constructs a new {@code AlreadyAuthorisedPanel}.
     243         * Constructs a new {@code AlreadyAUthorisedPanel}.
     244         * @param map The map with the authentication information
    219245         */
    220         AlreadyAuthorisedPanel() {
     246        AlreadyAuthorisedPanel(Map<String, String> map) {
     247            if (map == null) {
     248                map = new TreeMap<>();
     249                map.put("login", OAuthAccessTokenHolder.getInstance().getAccessTokenKey());
     250                map.put("password", OAuthAccessTokenHolder.getInstance().getAccessTokenSecret());
     251            }
     252            tfAccessTokenKey.setText(map.get("login"));
     253            tfAccessTokenSecret.setText(map.get("password"));
    221254            build();
    222             refreshView();
     255            refreshView(map);
    223256        }
    224257
    225258        protected void build() {
     
    291324            add(new JPanel(), gc);
    292325        }
    293326
    294         protected final void refreshView() {
    295             String v = OAuthAccessTokenHolder.getInstance().getAccessTokenKey();
     327        protected final void refreshView(Map<String, String> user) {
     328            String v = user.get("login");
    296329            tfAccessTokenKey.setText(v == null ? "" : v);
    297             v = OAuthAccessTokenHolder.getInstance().getAccessTokenSecret();
     330            v = user.get("password");
    298331            tfAccessTokenSecret.setText(v == null ? "" : v);
    299332            cbSaveToPreferences.setSelected(OAuthAccessTokenHolder.getInstance().isSaveToPreferences());
    300333        }
     
    374407            return;
    375408        setApiUrl((String) evt.getNewValue());
    376409    }
     410
     411    @Override
     412    public boolean equals(Object obj) {
     413        if (!(obj instanceof OAuthAuthenticationPreferencesPanel)) return false;
     414        OAuthAuthenticationPreferencesPanel check = (OAuthAuthenticationPreferencesPanel) obj;
     415        if (check.pnlAlreadyAuthorised == null && pnlAlreadyAuthorised == null) return true;
     416        if ((check.pnlAlreadyAuthorised == null && pnlAlreadyAuthorised != null)
     417                || (check.pnlAlreadyAuthorised != null && pnlAlreadyAuthorised == null)) return false;
     418
     419        if (check.pnlAlreadyAuthorised.tfAccessTokenKey.getText().equals(pnlAlreadyAuthorised.tfAccessTokenKey.getText())
     420                && check.pnlAlreadyAuthorised.tfAccessTokenSecret.getText().equals(pnlAlreadyAuthorised.tfAccessTokenSecret.getText())) {
     421            return true;
     422        }
     423        return false;
     424    }
     425
     426    @Override
     427    public int hashCode() {
     428        return super.hashCode();
     429    }
    377430}
  • src/org/openstreetmap/josm/io/OsmConnection.java

     
    104104     * Adds an authentication header for basic authentication
    105105     *
    106106     * @param con the connection
    107      * @throws OsmTransferException if something went wrong. Check for nested exceptions
     107     * @param response the response with username/password information
    108108     */
    109     protected void addBasicAuthorizationHeader(HttpClient con) throws OsmTransferException {
    110         CredentialsAgentResponse response;
    111         try {
    112             synchronized (CredentialsManager.getInstance()) {
    113                 response = CredentialsManager.getInstance().getCredentials(RequestorType.SERVER,
    114                 con.getURL().getHost(), false /* don't know yet whether the credentials will succeed */);
    115             }
    116         } catch (CredentialsAgentException e) {
    117             throw new OsmTransferException(e);
    118         }
     109    protected void addBasicAuthorizationHeader(HttpClient con, CredentialsAgentResponse response) {
    119110        if (response != null) {
    120111            if (response.isCanceled()) {
    121112                cancel = true;
     
    132123     * Signs the connection with an OAuth authentication header
    133124     *
    134125     * @param connection the connection
     126     * @param holder specific OAuth access token
    135127     *
    136128     * @throws MissingOAuthAccessTokenException if there is currently no OAuth Access Token configured
    137129     * @throws OsmTransferException if signing fails
    138130     */
    139     protected void addOAuthAuthorizationHeader(HttpClient connection) throws OsmTransferException {
     131    protected void addOAuthAuthorizationHeader(HttpClient connection, OAuthAccessTokenHolder holder) throws OsmTransferException {
    140132        if (oauthParameters == null) {
    141133            oauthParameters = OAuthParameters.createFromApiUrl(OsmApi.getOsmApi().getServerUrl());
    142134        }
    143135        OAuthConsumer consumer = oauthParameters.buildConsumer();
    144         OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();
    145136        if (!holder.containsAccessToken()) {
    146137            obtainAccessToken(connection);
    147138        }
     
    177168    }
    178169
    179170    protected void addAuth(HttpClient connection) throws OsmTransferException {
    180         final String authMethod = OsmApi.getAuthMethod();
    181         if ("basic".equals(authMethod)) {
    182             addBasicAuthorizationHeader(connection);
    183         } else if ("oauth".equals(authMethod)) {
    184             addOAuthAuthorizationHeader(connection);
     171        addAuth(connection, null);
     172    }
     173
     174    /**
     175     * Add authorization information to a connection
     176     * @param connection to add authorization information to
     177     * @param holder A {@code CredentialsAgentResponse} for basic authorization,
     178     * {@code OAuthAccessTokenHolder} for OAuth, or {@code null} for defaults.
     179     * @throws OsmTransferException if the authorization is not valid
     180     */
     181    protected void addAuth(HttpClient connection, Object holder) throws OsmTransferException {
     182        if (holder == null) {
     183            final String authMethod = OsmApi.getAuthMethod();
     184            if ("basic".equals(authMethod)) {
     185                CredentialsAgentResponse response;
     186                try {
     187                    synchronized (CredentialsManager.getInstance()) {
     188                        response = CredentialsManager.getInstance().getCredentials(RequestorType.SERVER,
     189                        connection.getURL().getHost(), false /* don't know yet whether the credentials will succeed */);
     190                    }
     191                } catch (CredentialsAgentException e) {
     192                    throw new OsmTransferException(e);
     193                }
     194                holder = response;
     195            } else if ("oauth".equals(authMethod)) {
     196                holder = OAuthAccessTokenHolder.getInstance();
     197            } else {
     198                String msg = tr("Unexpected value for preference ''{0}''. Got ''{1}''.", "osm-server.auth-method", authMethod);
     199                Logging.warn(msg);
     200                throw new OsmTransferException(msg);
     201            }
     202        }
     203
     204        if (holder instanceof OAuthAccessTokenHolder) {
     205            addOAuthAuthorizationHeader(connection, (OAuthAccessTokenHolder) holder);
     206        } else if (holder instanceof CredentialsAgentResponse) {
     207            addBasicAuthorizationHeader(connection, (CredentialsAgentResponse) holder);
    185208        } else {
    186             String msg = tr("Unexpected value for preference ''{0}''. Got ''{1}''.", "osm-server.auth-method", authMethod);
     209            String msg = tr("Unexpected object for authorizations. Got ''{0}''.", holder.getClass().getName());
    187210            Logging.warn(msg);
    188211            throw new OsmTransferException(msg);
    189212        }
  • src/org/openstreetmap/josm/io/OsmServerReader.java

     
    7979     * @throws OsmTransferException if data transfer errors occur
    8080     */
    8181    protected InputStream getInputStream(String urlStr, ProgressMonitor progressMonitor, String reason) throws OsmTransferException {
     82        return getInputStream(urlStr, progressMonitor, reason, null);
     83    }
     84
     85    /**
     86     * Open a connection to the given url and return a reader on the input stream
     87     * from that connection. In case of user cancel, return <code>null</code>.
     88     * Relative URL's are directed to API base URL.
     89     * @param urlStr The url to connect to.
     90     * @param progressMonitor progress monitoring and abort handler
     91     * @param reason The reason to show on console. Can be {@code null} if no reason is given
     92     * @param authentication A {@code CredentialsAgentResponse} for basic authorization,
     93     * {@code OAuthAccessTokenHolder} for OAuth, or {@code null} for defaults.
     94     * @return A reader reading the input stream (servers answer) or <code>null</code>.
     95     * @throws OsmTransferException if data transfer errors occur
     96     */
     97    protected InputStream getInputStream(String urlStr, ProgressMonitor progressMonitor, String reason, Object authentication)
     98            throws OsmTransferException {
    8299        try {
    83100            api.initialize(progressMonitor);
    84101            String url = urlStr.startsWith("http") ? urlStr : (getBaseUrl() + urlStr);
    85             return getInputStreamRaw(url, progressMonitor, reason);
     102            return getInputStreamRaw(url, progressMonitor, reason, authentication);
    86103        } finally {
    87104            progressMonitor.invalidate();
    88105        }
     
    122139    }
    123140
    124141    /**
     142     * Open a connection to the given url and return a reader on the input stream
     143     * from that connection. In case of user cancel, return <code>null</code>.
     144     * @param urlStr The exact url to connect to.
     145     * @param progressMonitor progress monitoring and abort handler
     146     * @param reason The reason to show on console. Can be {@code null} if no reason is given
     147     * @return An reader reading the input stream (servers answer) or <code>null</code>.
     148     * @throws OsmTransferException if data transfer errors occur
     149     * @since xxx
     150     */
     151    protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor, String reason, Object auth)
     152            throws OsmTransferException {
     153        return getInputStreamRaw(urlStr, progressMonitor, reason, false, "GET", null, auth);
     154    }
     155
     156    /**
    125157     * Open a connection to the given url (if HTTP, trough a GET request) and return a reader on the input stream
    126158     * from that connection. In case of user cancel, return <code>null</code>.
    127159     * @param urlStr The exact url to connect to.
     
    151183     * @throws OsmTransferException if data transfer errors occur
    152184     * @since 12596
    153185     */
     186    protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor, String reason,
     187            boolean uncompressAccordingToContentDisposition, String httpMethod, byte[] requestBody) throws OsmTransferException {
     188        return getInputStreamRaw(urlStr, progressMonitor, reason, uncompressAccordingToContentDisposition, httpMethod, requestBody, null);
     189    }
     190
     191    /**
     192     * Open a connection to the given url (if HTTP, with the specified method) and return a reader on the input stream
     193     * from that connection. In case of user cancel, return <code>null</code>.
     194     * @param urlStr The exact url to connect to.
     195     * @param progressMonitor progress monitoring and abort handler
     196     * @param reason The reason to show on console. Can be {@code null} if no reason is given
     197     * @param uncompressAccordingToContentDisposition Whether to inspect the HTTP header {@code Content-Disposition}
     198     *                                                for {@code filename} and uncompress a gzip/bzip2/xz/zip stream.
     199     * @param httpMethod HTTP method ("GET", "POST" or "PUT")
     200     * @param requestBody HTTP request body (for "POST" and "PUT" methods only). Must be null for "GET" method.
     201     * @param auth A {@code CredentialsAgentResponse} for basic authorization,
     202     * {@code OAuthAccessTokenHolder} for OAuth, or {@code null} for defaults.
     203     * @return An reader reading the input stream (servers answer) or {@code null}.
     204     * @throws OsmTransferException if data transfer errors occur
     205     * @since xxx
     206     */
    154207    @SuppressWarnings("resource")
    155208    protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor, String reason,
    156             boolean uncompressAccordingToContentDisposition, String httpMethod, byte[] requestBody) throws OsmTransferException {
     209            boolean uncompressAccordingToContentDisposition, String httpMethod, byte[] requestBody,
     210            Object auth) throws OsmTransferException {
    157211        try {
    158212            OnlineResource.JOSM_WEBSITE.checkOfflineAccess(urlStr, Config.getUrls().getJOSMWebsite());
    159213            OnlineResource.OSM_API.checkOfflineAccess(urlStr, OsmApi.getOsmApi().getServerUrl());
     
    182236            activeConnection = client;
    183237            adaptRequest(client);
    184238            if (doAuthenticate) {
    185                 addAuth(client);
     239                addAuth(client, auth);
    186240            }
    187241            if (cancel)
    188242                throw new OsmTransferCanceledException("Operation canceled");
     
    415469     */
    416470    public <T> T fetchData(String api, String subtask, DomParser<T> parser, ProgressMonitor monitor, String reason)
    417471            throws OsmTransferException {
     472        return fetchData(api, subtask, parser, monitor, reason, null);
     473    }
     474
     475    /**
     476     * Fetches generic data from the DOM document resulting an API call.
     477     * @param api the OSM API call
     478     * @param subtask the subtask translated message
     479     * @param parser the parser converting the DOM document (OSM API result)
     480     * @param <T> data type
     481     * @param monitor The progress monitor
     482     * @param reason The reason to show on console. Can be {@code null} if no reason is given
     483     * @param authentication A {@code CredentialsAgentResponse} for basic authorization,
     484     * {@code OAuthAccessTokenHolder} for OAuth, or {@code null} for defaults.
     485     * @return The converted data
     486     * @throws OsmTransferException if something goes wrong
     487     * @since 12510
     488     */
     489    public <T> T fetchData(String api, String subtask, DomParser<T> parser, ProgressMonitor monitor, String reason, Object authentication)
     490            throws OsmTransferException {
    418491        try {
    419492            monitor.beginTask("");
    420493            monitor.indeterminateSubTask(subtask);
    421             try (InputStream in = getInputStream(api, monitor.createSubTaskMonitor(1, true), reason)) {
     494            try (InputStream in = getInputStream(api, monitor.createSubTaskMonitor(1, true), reason, authentication)) {
    422495                return parser.parse(XmlUtils.parseSafeDOM(in));
    423496            }
    424497        } catch (OsmTransferException e) {
  • src/org/openstreetmap/josm/io/OsmServerUserInfoReader.java

     
    1313import javax.xml.xpath.XPathFactory;
    1414
    1515import org.openstreetmap.josm.data.coor.LatLon;
     16import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
    1617import org.openstreetmap.josm.data.osm.DataSet;
    1718import org.openstreetmap.josm.data.osm.UserInfo;
    1819import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     20import org.openstreetmap.josm.io.auth.CredentialsAgentResponse;
     21import org.openstreetmap.josm.tools.Logging;
    1922import org.openstreetmap.josm.tools.UncheckedParseException;
    2023import org.openstreetmap.josm.tools.XmlParsingException;
    2124import org.openstreetmap.josm.tools.date.DateUtils;
     
    159162    }
    160163
    161164    /**
     165     * Fetches user info without explicit reason with a specific authentication
     166     * @param monitor The progress monitor
     167     * @param authentication The authentication object ({@code OAuthAccessTokenHolder}
     168     * or {@code CredentialsAgentResponse})
     169     * @return The user info
     170     * @throws OsmTransferException if something goes wrong
     171     * @since xxx
     172     */
     173    public UserInfo fetchUserInfo(ProgressMonitor monitor, Object authentication) throws OsmTransferException {
     174        if (authentication instanceof String) {
     175            return fetchUserInfo(monitor, null, (String) authentication);
     176        } else {
     177            return fetchUserInfo(monitor, authentication, null);
     178        }
     179    }
     180
     181    /**
    162182     * Fetches user info, with an explicit reason.
    163183     * @param monitor The progress monitor
    164184     * @param reason The reason to show on console. Can be {@code null} if no reason is given
     
    167187     * @since 6695
    168188     */
    169189    public UserInfo fetchUserInfo(ProgressMonitor monitor, String reason) throws OsmTransferException {
    170         return fetchData("user/details", tr("Reading user info ..."),
    171                 OsmServerUserInfoReader::buildFromXML, monitor, reason);
     190        return fetchUserInfo(monitor, null, reason);
    172191    }
     192
     193    /**
     194     * Fetches user info, with an explicit reason.
     195     * @param monitor The progress monitor
     196     * @param authentication A {@code CredentialsAgentResponse} for basic authorization,
     197     * {@code OAuthAccessTokenHolder} for OAuth, or {@code null} for defaults.
     198     * @param reason The reason to show on console. Can be {@code null} if no reason is given
     199     * @return The user info
     200     * @throws OsmTransferException if something goes wrong
     201     * @since xxx
     202     */
     203    public UserInfo fetchUserInfo(ProgressMonitor monitor, Object authentication, String reason) throws OsmTransferException {
     204        if (authentication instanceof OAuthAccessTokenHolder || authentication instanceof CredentialsAgentResponse
     205                || authentication == null) {
     206            return fetchData("user/details", tr("Reading user info ..."),
     207                    OsmServerUserInfoReader::buildFromXML, monitor, reason, authentication);
     208        } else {
     209            String msg = tr("We did not get a valid authentication object ({0})", authentication.getClass().getName());
     210            Logging.warn(msg);
     211            throw new OsmTransferException(msg);
     212        }
     213    }
    173214}