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