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    }