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.Collections; 009import java.util.List; 010 011import javax.swing.JOptionPane; 012import javax.swing.SwingUtilities; 013 014import org.openstreetmap.josm.data.UserIdentityManager; 015import org.openstreetmap.josm.data.osm.Changeset; 016import org.openstreetmap.josm.data.osm.ChangesetCache; 017import org.openstreetmap.josm.data.osm.UserInfo; 018import org.openstreetmap.josm.gui.ExceptionDialogUtil; 019import org.openstreetmap.josm.gui.MainApplication; 020import org.openstreetmap.josm.gui.PleaseWaitRunnable; 021import org.openstreetmap.josm.gui.util.GuiHelper; 022import org.openstreetmap.josm.io.ChangesetQuery; 023import org.openstreetmap.josm.io.OsmServerChangesetReader; 024import org.openstreetmap.josm.io.OsmServerUserInfoReader; 025import org.openstreetmap.josm.io.OsmTransferException; 026import org.openstreetmap.josm.tools.Logging; 027import org.xml.sax.SAXException; 028 029/** 030 * This is a task for downloading the open changesets of the current user 031 * from the OSM server. 032 */ 033public class DownloadOpenChangesetsTask extends PleaseWaitRunnable { 034 035 private boolean canceled; 036 private OsmServerChangesetReader reader; 037 private List<Changeset> changesets; 038 private Exception lastException; 039 private final Component parent; 040 041 /** 042 * Constructs the task 043 * @param parent is a component to show error messages 044 */ 045 public DownloadOpenChangesetsTask(Component parent) { 046 super(parent, tr("Downloading open changesets ..."), false /* don't ignore exceptions */); 047 this.parent = parent; 048 } 049 050 @Override 051 protected void cancel() { 052 this.canceled = true; 053 synchronized (this) { 054 if (reader != null) { 055 reader.cancel(); 056 } 057 } 058 } 059 060 @Override 061 protected void finish() { 062 if (UserIdentityManager.getInstance().isAnonymous()) { 063 String msg = 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 Logging.warn(msg); 068 JOptionPane.showMessageDialog(GuiHelper.getFrameForComponent(parent), 069 "<html>" + msg + "</html>", tr("Missing user identity"), JOptionPane.ERROR_MESSAGE); 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 MainApplication.getMainFrame(), 080 tr("There are no open changesets"), 081 tr("No open changesets"), 082 JOptionPane.INFORMATION_MESSAGE 083 ); 084 return; 085 } 086 SwingUtilities.invokeLater(() -> ChangesetCache.getInstance().update(changesets)); 087 } 088 089 /** 090 * Refreshes the user info from the server. This is necessary if we don't know the users id yet. 091 */ 092 protected void refreshUserIdentity() { 093 UserIdentityManager im = UserIdentityManager.getInstance(); 094 try { 095 OsmServerUserInfoReader infoReader = new OsmServerUserInfoReader(); 096 UserInfo info = infoReader.fetchUserInfo(getProgressMonitor().createSubTaskMonitor(1, false)); 097 im.setFullyIdentified(info.getDisplayName(), info); 098 } catch (OsmTransferException e) { 099 // retrieving the user info can fail if the current user is not authorised to 100 // retrieve it, i.e. if he is working with an OAuth Access Token which doesn't 101 // have the respective privileges or if he didn't or he can't authenticate with 102 // a username/password-pair. 103 // 104 // Downgrade your knowledge about its identity if we've assumed that he was fully 105 // identified. Otherwise, if he is anonymous or partially identified, keep our level 106 // of knowledge. 107 // 108 if (im.isFullyIdentified()) { 109 im.setPartiallyIdentified(im.getUserName()); 110 } 111 Logging.log(Logging.LEVEL_WARN, 112 tr("Failed to retrieve user infos for the current JOSM user. Exception was: {0}", e.toString()), e); 113 } 114 } 115 116 @Override 117 protected void realRun() throws SAXException, IOException, OsmTransferException { 118 try { 119 UserIdentityManager im = UserIdentityManager.getInstance(); 120 if (im.isAnonymous()) { 121 refreshUserIdentity(); 122 } else if (im.isFullyIdentified()) { 123 // do nothing 124 } else if (im.isPartiallyIdentified()) { 125 refreshUserIdentity(); 126 } 127 if (canceled) return; 128 synchronized (this) { 129 reader = new OsmServerChangesetReader(); 130 } 131 ChangesetQuery query = new ChangesetQuery().beingOpen(true); 132 if (im.isAnonymous()) 133 // we still don't know anything about the current user. Can't retrieve 134 // its changesets 135 return; 136 else if (im.isFullyIdentified()) { 137 query = query.forUser(im.getUserId()); 138 } else { 139 // we only know the users name, not its id. Nevermind, try to read 140 // its open changesets anyway. 141 // 142 query = query.forUser(im.getUserName()); 143 } 144 changesets = reader.queryChangesets( 145 query, 146 getProgressMonitor().createSubTaskMonitor(1, false /* not internal */) 147 ); 148 } catch (OsmTransferException e) { 149 if (canceled) 150 return; 151 lastException = e; 152 } 153 } 154 155 /** 156 * Determines if this task has been cancelled. 157 * @return {@code true} if this task has been cancelled 158 */ 159 public boolean isCanceled() { 160 return canceled; 161 } 162 163 /** 164 * Returns the changesets. 165 * @return the changesets, or {@code null} 166 * @since 11110 167 */ 168 public final List<Changeset> getChangesets() { 169 return changesets != null ? Collections.unmodifiableList(changesets) : null; 170 } 171}