001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io.auth; 003 004import java.awt.GraphicsEnvironment; 005import java.net.Authenticator.RequestorType; 006import java.net.PasswordAuthentication; 007import java.util.EnumMap; 008import java.util.Map; 009 010import org.openstreetmap.josm.gui.io.CredentialDialog; 011import org.openstreetmap.josm.gui.util.GuiHelper; 012 013public abstract class AbstractCredentialsAgent implements CredentialsAgent { 014 015 protected Map<RequestorType, PasswordAuthentication> memoryCredentialsCache = new EnumMap<>(RequestorType.class); 016 017 @Override 018 public CredentialsAgentResponse getCredentials(final RequestorType requestorType, final String host, boolean noSuccessWithLastResponse) 019 throws CredentialsAgentException { 020 if (requestorType == null) 021 return null; 022 PasswordAuthentication credentials = lookup(requestorType, host); 023 final String username = (credentials == null || credentials.getUserName() == null) ? "" : credentials.getUserName(); 024 final String password = (credentials == null || credentials.getPassword() == null) ? "" : String.valueOf(credentials.getPassword()); 025 026 final CredentialsAgentResponse response = new CredentialsAgentResponse(); 027 028 /* 029 * Last request was successful and there was no credentials stored 030 * in file (or only the username is stored). 031 * -> Try to recall credentials that have been entered 032 * manually in this session. 033 */ 034 if (!noSuccessWithLastResponse && memoryCredentialsCache.containsKey(requestorType) && 035 (credentials == null || credentials.getPassword() == null || credentials.getPassword().length == 0)) { 036 PasswordAuthentication pa = memoryCredentialsCache.get(requestorType); 037 response.setUsername(pa.getUserName()); 038 response.setPassword(pa.getPassword()); 039 response.setCanceled(false); 040 /* 041 * Prompt the user for credentials. This happens the first time each 042 * josm start if the user does not save the credentials to preference 043 * file (username=="") and each time after authentication failed 044 * (noSuccessWithLastResponse == true). 045 */ 046 } else if (noSuccessWithLastResponse || username.isEmpty() || password.isEmpty()) { 047 if (!GraphicsEnvironment.isHeadless()) { 048 GuiHelper.runInEDTAndWait(new Runnable() { 049 @Override 050 public void run() { 051 CredentialDialog dialog; 052 if (requestorType.equals(RequestorType.PROXY)) 053 dialog = CredentialDialog.getHttpProxyCredentialDialog( 054 username, password, host, getSaveUsernameAndPasswordCheckboxText()); 055 else 056 dialog = CredentialDialog.getOsmApiCredentialDialog( 057 username, password, host, getSaveUsernameAndPasswordCheckboxText()); 058 dialog.setVisible(true); 059 response.setCanceled(dialog.isCanceled()); 060 if (dialog.isCanceled()) 061 return; 062 response.setUsername(dialog.getUsername()); 063 response.setPassword(dialog.getPassword()); 064 response.setSaveCredentials(dialog.isSaveCredentials()); 065 } 066 }); 067 } 068 if (response.isCanceled() || response.getUsername() == null || response.getPassword() == null) { 069 return response; 070 } 071 if (response.isSaveCredentials()) { 072 store(requestorType, host, new PasswordAuthentication( 073 response.getUsername(), 074 response.getPassword() 075 )); 076 /* 077 * User decides not to save credentials to file. Keep it 078 * in memory so we don't have to ask over and over again. 079 */ 080 } else { 081 PasswordAuthentication pa = new PasswordAuthentication(response.getUsername(), response.getPassword()); 082 memoryCredentialsCache.put(requestorType, pa); 083 } 084 /* 085 * We got it from file. 086 */ 087 } else { 088 response.setUsername(username); 089 response.setPassword(password.toCharArray()); 090 response.setCanceled(false); 091 } 092 return response; 093 } 094 095 /** 096 * Provide the text for a checkbox that offers to save the 097 * username and password that has been entered by the user. 098 * @return checkbox text 099 */ 100 public abstract String getSaveUsernameAndPasswordCheckboxText(); 101}