001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.gui.io;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.awt.Component;
007 import java.io.IOException;
008 import java.util.List;
009
010 import javax.swing.JOptionPane;
011 import javax.swing.SwingUtilities;
012
013 import org.openstreetmap.josm.Main;
014 import org.openstreetmap.josm.data.osm.Changeset;
015 import org.openstreetmap.josm.data.osm.ChangesetCache;
016 import org.openstreetmap.josm.data.osm.UserInfo;
017 import org.openstreetmap.josm.gui.ExceptionDialogUtil;
018 import org.openstreetmap.josm.gui.JosmUserIdentityManager;
019 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
020 import org.openstreetmap.josm.io.ChangesetQuery;
021 import org.openstreetmap.josm.io.OsmServerChangesetReader;
022 import org.openstreetmap.josm.io.OsmServerUserInfoReader;
023 import org.openstreetmap.josm.io.OsmTransferException;
024 import org.xml.sax.SAXException;
025
026 /**
027 * This is a task for downloading the open changesets of the current user
028 * from the OSM server.
029 */
030 public class DownloadOpenChangesetsTask extends PleaseWaitRunnable {
031
032 private boolean canceled;
033 private OsmServerChangesetReader reader;
034 private List<Changeset> changesets;
035 private Exception lastException;
036 private Component parent;
037
038 /**
039 *
040 * @param model provides the user id of the current user and accepts the changesets
041 * after download
042 */
043 public DownloadOpenChangesetsTask(Component parent) {
044 super(parent, tr("Downloading open changesets ..."), false /* don't ignore exceptions */);
045 this.parent = parent;
046 }
047
048 @Override
049 protected void cancel() {
050 this.canceled = true;
051 synchronized(this) {
052 if (reader != null) {
053 reader.cancel();
054 }
055 }
056 }
057
058 @Override
059 protected void finish() {
060 if (JosmUserIdentityManager.getInstance().isAnonymous()) {
061 JOptionPane.showMessageDialog(
062 JOptionPane.getFrameForComponent(parent),
063 "<html>" + tr("Could not retrieve the list of your open changesets because<br>"
064 + "JOSM does not know your identity.<br>"
065 + "You have either chosen to work anonymously or you are not entitled<br>"
066 + "to know the identity of the user on whose behalf you are working.")
067 + "</html>",
068 tr("Missing user identity"),
069 JOptionPane.ERROR_MESSAGE
070 );
071 return;
072 }
073 if (canceled)return;
074 if (lastException != null) {
075 ExceptionDialogUtil.explainException(lastException);
076 return;
077 }
078 if (changesets.isEmpty()) {
079 JOptionPane.showMessageDialog(
080 Main.parent,
081 tr("There are no open changesets"),
082 tr("No open changesets"),
083 JOptionPane.INFORMATION_MESSAGE
084 );
085 return;
086 }
087 SwingUtilities.invokeLater(
088 new Runnable() {
089 public void run() {
090 ChangesetCache.getInstance().update(changesets);
091 }
092 }
093 );
094 }
095
096 /**
097 * Refreshes the user info from the server. This is necessary if we don't know
098 * the users id yet.
099 *
100 */
101 protected void refreshUserIdentity(){
102 JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
103 try {
104 OsmServerUserInfoReader reader = new OsmServerUserInfoReader();
105 UserInfo info = reader.fetchUserInfo(getProgressMonitor().createSubTaskMonitor(1, false));
106 im.setFullyIdentified(info.getDisplayName(), info);
107 } catch(OsmTransferException e) {
108 // retrieving the user info can fail if the current user is not authorised to
109 // retrieve it, i.e. if he is working with an OAuth Access Token which doesn't
110 // have the respective privileges or if he didn't or he can't authenticate with
111 // a username/password-pair.
112 //
113 // Downgrade your knowlege about its identity if we've assumed that he was fully
114 // identified. Otherwise, if he is anonymous or partially identified, keep our level
115 // of knowlege.
116 //
117 if (im.isFullyIdentified()) {
118 im.setPartiallyIdentified(im.getUserName());
119 }
120 System.err.println(tr("Warning: Failed to retrieve user infos for the current JOSM user. Exception was: {0}", e.toString()));
121 }
122 }
123
124 @Override
125 protected void realRun() throws SAXException, IOException, OsmTransferException {
126 try {
127 JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
128 if (im.isAnonymous()) {
129 refreshUserIdentity();
130 } else if (im.isFullyIdentified()){
131 // do nothing
132 } else if (im.isPartiallyIdentified()) {
133 refreshUserIdentity();
134 }
135 if (canceled)return;
136 synchronized(this) {
137 reader = new OsmServerChangesetReader();
138 }
139 ChangesetQuery query = new ChangesetQuery().beingOpen(true);
140 if (im.isAnonymous())
141 // we still don't know anything about the current user. Can't retrieve
142 // its changesets
143 return;
144 else if (im.isFullyIdentified()) {
145 query = query.forUser(im.getUserId());
146 } else {
147 // we only know the users name, not its id. Nevermind, try to read
148 // its open changesets anyway.
149 //
150 query = query.forUser(im.getUserName());
151 }
152 changesets = reader.queryChangesets(
153 query,
154 getProgressMonitor().createSubTaskMonitor(1, false /* not internal */)
155 );
156 } catch(Exception e) {
157 if (canceled)
158 return;
159 lastException = e;
160 }
161 }
162
163 public boolean isCanceled() {
164 return canceled;
165 }
166 }