001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io.auth; 003 004import java.awt.Component; 005import java.net.Authenticator.RequestorType; 006import java.net.PasswordAuthentication; 007import java.util.Objects; 008 009import org.openstreetmap.josm.Main; 010import org.openstreetmap.josm.data.oauth.OAuthToken; 011import org.openstreetmap.josm.gui.JosmUserIdentityManager; 012import org.openstreetmap.josm.io.OsmApi; 013import org.openstreetmap.josm.tools.CheckParameterUtil; 014 015/** 016 * CredentialManager is a factory for the single credential agent used. 017 * 018 * Currently, it defaults to replying an instance of {@link JosmPreferencesCredentialAgent}. 019 * @since 2641 020 */ 021public class CredentialsManager implements CredentialsAgent { 022 023 private static volatile CredentialsManager instance; 024 025 /** 026 * Replies the single credential agent used in JOSM 027 * 028 * @return the single credential agent used in JOSM 029 */ 030 public static CredentialsManager getInstance() { 031 if (instance == null) { 032 CredentialsAgent delegate; 033 if (agentFactory == null) { 034 delegate = new JosmPreferencesCredentialAgent(); 035 } else { 036 delegate = agentFactory.getCredentialsAgent(); 037 } 038 instance = new CredentialsManager(delegate); 039 } 040 return instance; 041 } 042 043 private static CredentialsAgentFactory agentFactory; 044 045 @FunctionalInterface 046 public interface CredentialsAgentFactory { 047 CredentialsAgent getCredentialsAgent(); 048 } 049 050 /** 051 * Plugins can register a CredentialsAgentFactory, thereby overriding 052 * JOSM's default credentials agent. 053 * @param agentFactory The Factory that provides the custom CredentialsAgent. 054 * Can be null to clear the factory and switch back to default behavior. 055 */ 056 public static void registerCredentialsAgentFactory(CredentialsAgentFactory agentFactory) { 057 CredentialsManager.agentFactory = agentFactory; 058 CredentialsManager.instance = null; 059 } 060 061 /* non-static fields and methods */ 062 063 /** 064 * The credentials agent doing the real stuff 065 */ 066 private final CredentialsAgent delegate; 067 068 /** 069 * Constructs a new {@code CredentialsManager}. 070 * @param delegate The credentials agent backing this credential manager. Must not be {@code null} 071 */ 072 public CredentialsManager(CredentialsAgent delegate) { 073 CheckParameterUtil.ensureParameterNotNull(delegate, "delegate"); 074 this.delegate = delegate; 075 } 076 077 /** 078 * Returns type of credentials agent backing this credentials manager. 079 * @return The type of credentials agent 080 */ 081 public final Class<? extends CredentialsAgent> getCredentialsAgentClass() { 082 return delegate.getClass(); 083 } 084 085 /** 086 * Returns the username for OSM API 087 * @return the username for OSM API 088 */ 089 public String getUsername() { 090 return getUsername(OsmApi.getOsmApi().getHost()); 091 } 092 093 /** 094 * Returns the username for a given host 095 * @param host The host for which username is wanted 096 * @return The username for {@code host} 097 */ 098 public String getUsername(String host) { 099 String username = null; 100 try { 101 PasswordAuthentication auth = lookup(RequestorType.SERVER, host); 102 if (auth != null) { 103 username = auth.getUserName(); 104 } 105 } catch (CredentialsAgentException ex) { 106 Main.debug(ex); 107 return null; 108 } 109 if (username == null) return null; 110 username = username.trim(); 111 return username.isEmpty() ? null : username; 112 } 113 114 @Override 115 public PasswordAuthentication lookup(RequestorType requestorType, String host) throws CredentialsAgentException { 116 return delegate.lookup(requestorType, host); 117 } 118 119 @Override 120 public void store(RequestorType requestorType, String host, PasswordAuthentication credentials) throws CredentialsAgentException { 121 if (requestorType == RequestorType.SERVER && Objects.equals(OsmApi.getOsmApi().getHost(), host)) { 122 String username = credentials.getUserName(); 123 if (username != null && !username.trim().isEmpty()) { 124 JosmUserIdentityManager.getInstance().setPartiallyIdentified(username); 125 } 126 } 127 delegate.store(requestorType, host, credentials); 128 } 129 130 @Override 131 public CredentialsAgentResponse getCredentials(RequestorType requestorType, String host, boolean noSuccessWithLastResponse) 132 throws CredentialsAgentException { 133 return delegate.getCredentials(requestorType, host, noSuccessWithLastResponse); 134 } 135 136 @Override 137 public OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException { 138 return delegate.lookupOAuthAccessToken(); 139 } 140 141 @Override 142 public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException { 143 delegate.storeOAuthAccessToken(accessToken); 144 } 145 146 @Override 147 public Component getPreferencesDecorationPanel() { 148 return delegate.getPreferencesDecorationPanel(); 149 } 150}