source: josm/trunk/src/org/openstreetmap/josm/gui/JosmUserIdentityManager.java@ 6789

Last change on this file since 6789 was 6643, checked in by Don-vip, 10 years ago

global replacement of e.printStackTrace() by Main.error(e)

  • Property svn:eol-style set to native
File size: 10.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.text.MessageFormat;
8
9import org.openstreetmap.josm.Main;
10import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
11import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
12import org.openstreetmap.josm.data.Preferences.StringSetting;
13import org.openstreetmap.josm.data.osm.UserInfo;
14import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
15import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
16import org.openstreetmap.josm.io.OsmApi;
17import org.openstreetmap.josm.io.OsmServerUserInfoReader;
18import org.openstreetmap.josm.io.OsmTransferException;
19import org.openstreetmap.josm.io.auth.CredentialsManager;
20import org.openstreetmap.josm.tools.CheckParameterUtil;
21
22/**
23 * JosmUserStateManager is a global object which keeps track of what JOSM knows about
24 * the identity of the current user.
25 *
26 * JOSM can be operated anonymously provided the current user never invokes an operation
27 * on the OSM server which required authentication. In this case JOSM neither knows
28 * the user name of the OSM account of the current user nor its unique id. Perhaps the
29 * user doesn't have one.
30 *
31 * If the current user supplies a user name and a password in the JOSM preferences JOSM
32 * can partially identify the user.
33 *
34 * The current user is fully identified if JOSM knows both the user name and the unique
35 * id of the users OSM account. The latter is retrieved from the OSM server with a
36 * <tt>GET /api/0.6/user/details</tt> request, submitted with the user name and password
37 * of the current user.
38 *
39 * The global JosmUserStateManager listens to {@link PreferenceChangeEvent}s and keeps track
40 * of what the current JOSM instance knows about the current user. Other subsystems can
41 * let the global JosmUserStateManager know in case they fully identify the current user, see
42 * {@link #setFullyIdentified}.
43 *
44 * The information kept by the JosmUserStateManager can be used to
45 * <ul>
46 * <li>safely query changesets owned by the current user based on its user id, not on its user name</li>
47 * <li>safely search for objects last touched by the current user based on its user id, not on its user name</li>
48 * </ul>
49 *
50 */
51public final class JosmUserIdentityManager implements PreferenceChangedListener{
52
53 static private JosmUserIdentityManager instance;
54
55 /**
56 * Replies the unique instance of the JOSM user identity manager
57 *
58 * @return the unique instance of the JOSM user identity manager
59 */
60 static public JosmUserIdentityManager getInstance() {
61 if (instance == null) {
62 instance = new JosmUserIdentityManager();
63 if (OsmApi.isUsingOAuth() && OAuthAccessTokenHolder.getInstance().containsAccessToken()) {
64 try {
65 instance.initFromOAuth(Main.parent);
66 } catch (Throwable t) {
67 Main.error(t);
68 // Fall back to preferences if OAuth identification fails for any reason
69 instance.initFromPreferences();
70 }
71 } else {
72 instance.initFromPreferences();
73 }
74 Main.pref.addPreferenceChangeListener(instance);
75 }
76 return instance;
77 }
78
79 private String userName;
80 private UserInfo userInfo;
81 private boolean accessTokenKeyChanged;
82 private boolean accessTokenSecretChanged;
83
84 private JosmUserIdentityManager() {
85 }
86
87 /**
88 * Remembers the fact that the current JOSM user is anonymous.
89 */
90 public void setAnonymous() {
91 userName = null;
92 userInfo = null;
93 }
94
95 /**
96 * Remebers the fact that the current JOSM user is partially identified
97 * by the user name of its OSM account.
98 *
99 * @param userName the user name. Must not be null. Must not be empty (whitespace only).
100 * @throws IllegalArgumentException thrown if userName is null
101 * @throws IllegalArgumentException thrown if userName is empty
102 */
103 public void setPartiallyIdentified(String userName) throws IllegalArgumentException {
104 CheckParameterUtil.ensureParameterNotNull(userName, "userName");
105 if (userName.trim().isEmpty())
106 throw new IllegalArgumentException(MessageFormat.format("Expected non-empty value for parameter ''{0}'', got ''{1}''", "userName", userName));
107 this.userName = userName;
108 userInfo = null;
109 }
110
111 /**
112 * Remembers the fact that the current JOSM user is fully identified with a
113 * verified pair of user name and user id.
114 *
115 * @param username the user name. Must not be null. Must not be empty.
116 * @param userinfo additional information about the user, retrieved from the OSM server and including the user id
117 * @throws IllegalArgumentException thrown if userName is null
118 * @throws IllegalArgumentException thrown if userName is empty
119 * @throws IllegalArgumentException thrown if userinfo is null
120 */
121 public void setFullyIdentified(String username, UserInfo userinfo) throws IllegalArgumentException {
122 CheckParameterUtil.ensureParameterNotNull(username, "username");
123 if (username.trim().isEmpty())
124 throw new IllegalArgumentException(tr("Expected non-empty value for parameter ''{0}'', got ''{1}''", "userName", userName));
125 CheckParameterUtil.ensureParameterNotNull(userinfo, "userinfo");
126 this.userName = username;
127 this.userInfo = userinfo;
128 }
129
130 /**
131 * Replies true if the current JOSM user is anonymous.
132 *
133 * @return {@code true} if the current user is anonymous.
134 */
135 public boolean isAnonymous() {
136 return userName == null && userInfo == null;
137 }
138
139 /**
140 * Replies true if the current JOSM user is partially identified.
141 *
142 * @return true if the current JOSM user is partially identified.
143 */
144 public boolean isPartiallyIdentified() {
145 return userName != null && userInfo == null;
146 }
147
148 /**
149 * Replies true if the current JOSM user is fully identified.
150 *
151 * @return true if the current JOSM user is fully identified.
152 */
153 public boolean isFullyIdentified() {
154 return userName != null && userInfo != null;
155 }
156
157 /**
158 * Replies the user name of the current JOSM user. null, if {@link #isAnonymous()} is true.
159 *
160 * @return the user name of the current JOSM user
161 */
162 public String getUserName() {
163 return userName;
164 }
165
166 /**
167 * Replies the user id of the current JOSM user. 0, if {@link #isAnonymous()} or
168 * {@link #isPartiallyIdentified()} is true.
169 *
170 * @return the user id of the current JOSM user
171 */
172 public int getUserId() {
173 if (userInfo == null) return 0;
174 return userInfo.getId();
175 }
176
177 /**
178 * Replies verified additional information about the current user if the user is
179 * {@link #isFullyIdentified()}.
180 *
181 * @return verified additional information about the current user
182 */
183 public UserInfo getUserInfo() {
184 return userInfo;
185 }
186
187 /**
188 * Initializes the user identity manager from Basic Authentication values in the {@link org.openstreetmap.josm.data.Preferences}
189 * This method should be called if {@code osm-server.auth-method} is set to {@code basic}.
190 * @see #initFromOAuth
191 */
192 public void initFromPreferences() {
193 String userName = CredentialsManager.getInstance().getUsername();
194 if (isAnonymous()) {
195 if (userName != null && !userName.trim().isEmpty()) {
196 setPartiallyIdentified(userName);
197 }
198 } else {
199 if (userName != null && !userName.equals(this.userName)) {
200 setPartiallyIdentified(userName);
201 } else {
202 // same name in the preferences as JOSM already knows about.
203 // keep the state, be it partially or fully identified
204 }
205 }
206 }
207
208 /**
209 * Initializes the user identity manager from OAuth request of user details.
210 * This method should be called if {@code osm-server.auth-method} is set to {@code oauth}.
211 * @param parent component relative to which the {@link PleaseWaitDialog} is displayed.
212 * @see #initFromPreferences
213 * @since 5434
214 */
215 public void initFromOAuth(Component parent) {
216 try {
217 UserInfo info = new OsmServerUserInfoReader().fetchUserInfo(NullProgressMonitor.INSTANCE);
218 setFullyIdentified(info.getDisplayName(), info);
219 } catch (IllegalArgumentException e) {
220 Main.error(e);
221 } catch (OsmTransferException e) {
222 Main.error(e);
223 }
224 }
225
226 /**
227 * Replies true if the user with name <code>username</code> is the current
228 * user
229 *
230 * @param username the user name
231 * @return true if the user with name <code>username</code> is the current
232 * user
233 */
234 public boolean isCurrentUser(String username) {
235 if (username == null || this.userName == null) return false;
236 return this.userName.equals(username);
237 }
238
239 /* ------------------------------------------------------------------- */
240 /* interface PreferenceChangeListener */
241 /* ------------------------------------------------------------------- */
242 @Override
243 public void preferenceChanged(PreferenceChangeEvent evt) {
244 if (evt.getKey().equals("osm-server.username")) {
245 if (!(evt.getNewValue() instanceof StringSetting)) return;
246 String newValue = ((StringSetting) evt.getNewValue()).getValue();
247 if (newValue == null || newValue.trim().length() == 0) {
248 setAnonymous();
249 } else {
250 if (! newValue.equals(userName)) {
251 setPartiallyIdentified(newValue);
252 }
253 }
254 return;
255
256 } else if (evt.getKey().equals("osm-server.url")) {
257 if (!(evt.getNewValue() instanceof StringSetting)) return;
258 String newValue = ((StringSetting) evt.getNewValue()).getValue();
259 if (newValue == null || newValue.trim().isEmpty()) {
260 setAnonymous();
261 } else if (isFullyIdentified()) {
262 setPartiallyIdentified(getUserName());
263 }
264
265 } else if (evt.getKey().equals("oauth.access-token.key")) {
266 accessTokenKeyChanged = true;
267
268 } else if (evt.getKey().equals("oauth.access-token.secret")) {
269 accessTokenSecretChanged = true;
270 }
271
272 if (accessTokenKeyChanged && accessTokenSecretChanged) {
273 accessTokenKeyChanged = false;
274 accessTokenSecretChanged = false;
275 if (OsmApi.isUsingOAuth()) {
276 try {
277 instance.initFromOAuth(Main.parent);
278 } catch (Throwable t) {
279 Main.error(t);
280 }
281 }
282 }
283 }
284}
Note: See TracBrowser for help on using the repository browser.