// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.io.auth;
import java.awt.GraphicsEnvironment;
import java.net.Authenticator.RequestorType;
import java.net.PasswordAuthentication;
import java.util.EnumMap;
import java.util.Map;
import org.openstreetmap.josm.gui.io.CredentialDialog;
import org.openstreetmap.josm.gui.util.GuiHelper;
public abstract class AbstractCredentialsAgent implements CredentialsAgent {
protected Map<RequestorType, PasswordAuthentication> memoryCredentialsCache = new EnumMap<>(RequestorType.class);
@Override
public CredentialsAgentResponse getCredentials(final RequestorType requestorType, final String host, boolean noSuccessWithLastResponse)
throws CredentialsAgentException {
if (requestorType == null)
return null;
PasswordAuthentication credentials = lookup(requestorType, host);
final String username = (credentials == null || credentials.getUserName() == null) ? "" : credentials.getUserName();
final String password = (credentials == null || credentials.getPassword() == null) ? "" : String.valueOf(credentials.getPassword());
final CredentialsAgentResponse response = new CredentialsAgentResponse();
/*
* Last request was successful and there was no credentials stored
* in file (or only the username is stored).
* -> Try to recall credentials that have been entered
* manually in this session.
*/
if (!noSuccessWithLastResponse && memoryCredentialsCache.containsKey(requestorType) &&
(credentials == null || credentials.getPassword() == null || credentials.getPassword().length == 0)) {
PasswordAuthentication pa = memoryCredentialsCache.get(requestorType);
response.setUsername(pa.getUserName());
response.setPassword(pa.getPassword());
response.setCanceled(false);
/*
* Prompt the user for credentials. This happens the first time each
* josm start if the user does not save the credentials to preference
* file (username=="") and each time after authentication failed
* (noSuccessWithLastResponse == true).
*/
} else if (noSuccessWithLastResponse || username.isEmpty() || password.isEmpty()) {
if (!GraphicsEnvironment.isHeadless()) {
GuiHelper.runInEDTAndWait(() -> {
CredentialDialog dialog;
if (requestorType.equals(RequestorType.PROXY))
dialog = CredentialDialog.getHttpProxyCredentialDialog(
username, password, host, getSaveUsernameAndPasswordCheckboxText());
else
dialog = CredentialDialog.getOsmApiCredentialDialog(
username, password, host, getSaveUsernameAndPasswordCheckboxText());
dialog.setVisible(true);
response.setCanceled(dialog.isCanceled());
if (dialog.isCanceled())
return;
response.setUsername(dialog.getUsername());
response.setPassword(dialog.getPassword());
response.setSaveCredentials(dialog.isSaveCredentials());
});
}
if (response.isCanceled() || response.getUsername() == null || response.getPassword() == null) {
return response;
}
if (response.isSaveCredentials()) {
store(requestorType, host, new PasswordAuthentication(
response.getUsername(),
response.getPassword()
));
/*
* User decides not to save credentials to file. Keep it
* in memory so we don't have to ask over and over again.
*/
} else {
PasswordAuthentication pa = new PasswordAuthentication(response.getUsername(), response.getPassword());
memoryCredentialsCache.put(requestorType, pa);
}
/*
* We got it from file.
*/
} else {
response.setUsername(username);
response.setPassword(password.toCharArray());
response.setCanceled(false);
}
return response;
}
/**
* Provide the text for a checkbox that offers to save the
* username and password that has been entered by the user.
* @return checkbox text
*/
public abstract String getSaveUsernameAndPasswordCheckboxText();
}