Changeset 7434 in josm


Ignore:
Timestamp:
2014-08-20T03:07:15+02:00 (10 years ago)
Author:
Don-vip
Message:

fix #8885 (see #4614) - add offline mode with new command line argument --offline which can take one of several of these values (comma separated):

  • josm_website: to disable all accesses to JOSM website (when not cached, disables Getting Started page, help, plugin list, styles, imagery, presets, rules)
  • osm_api: to disable all accesses to OSM API (disables download, upload, changeset queries, history, user message notification)
  • all: alias to disable all values. Currently equivalent to "josm_website,osm_api"

Plus improved javadoc, fixed EDT violations, and fixed a bug with HTTP redirection sent without "Location" header

Location:
trunk/src/org/openstreetmap/josm
Files:
2 added
39 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/Main.java

    r7420 r7434  
    2525import java.util.Collections;
    2626import java.util.HashMap;
     27import java.util.HashSet;
    2728import java.util.Iterator;
    2829import java.util.List;
    2930import java.util.Map;
    3031import java.util.Objects;
     32import java.util.Set;
    3133import java.util.StringTokenizer;
    3234import java.util.concurrent.Callable;
     
    9193import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
    9294import org.openstreetmap.josm.io.FileWatcher;
     95import org.openstreetmap.josm.io.OnlineResource;
    9396import org.openstreetmap.josm.io.OsmApi;
    9497import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    219222    private static final List<String> ERRORS_AND_WARNINGS = Collections.<String>synchronizedList(new ArrayList<String>());
    220223
     224    private static final Set<OnlineResource> OFFLINE_RESOURCES = new HashSet<>();
     225
    221226    /**
    222227     * Logging level (5 = trace, 4 = debug, 3 = info, 2 = warn, 1 = error, 0 = none).
     
    543548        List<Callable<Void>> tasks = new ArrayList<>();
    544549
    545         tasks.add(new InitializationTask(tr("Initializing OSM API")) {
    546 
    547             @Override
    548             public void initialize() throws Exception {
    549                 // We try to establish an API connection early, so that any API
    550                 // capabilities are already known to the editor instance. However
    551                 // if it goes wrong that's not critical at this stage.
    552                 try {
    553                     OsmApi.getOsmApi().initialize(null, true);
    554                 } catch (Exception e) {
    555                     Main.warn(getErrorMessage(Utils.getRootCause(e)));
     550        if (isOffline(OnlineResource.OSM_API)) {
     551            Main.warn(tr("{0} not available (offline mode)", tr("OSM API")));
     552        } else {
     553            tasks.add(new InitializationTask(tr("Initializing OSM API")) {
     554
     555                @Override
     556                public void initialize() throws Exception {
     557                    // We try to establish an API connection early, so that any API
     558                    // capabilities are already known to the editor instance. However
     559                    // if it goes wrong that's not critical at this stage.
     560                    try {
     561                        OsmApi.getOsmApi().initialize(null, true);
     562                    } catch (Exception e) {
     563                        Main.warn(getErrorMessage(Utils.getRootCause(e)));
     564                    }
    556565                }
    557             }
    558         });
     566            });
     567        }
    559568
    560569        tasks.add(new InitializationTask(tr("Initializing validator")) {
     
    15531562        return Main.platform instanceof PlatformHookWindows;
    15541563    }
     1564
     1565    /**
     1566     * Determines if the given online resource is currently offline.
     1567     * @param r the online resource
     1568     * @return {@code true} if {@code r} is offline and should not be accessed
     1569     * @since 7434
     1570     */
     1571    public static boolean isOffline(OnlineResource r) {
     1572        return OFFLINE_RESOURCES.contains(r) || OFFLINE_RESOURCES.contains(OnlineResource.ALL);
     1573    }
     1574
     1575    /**
     1576     * Sets the given online resource to offline state.
     1577     * @param r the online resource
     1578     * @return {@code true} if {@code r} was not already offline
     1579     * @since 7434
     1580     */
     1581    public static boolean setOffline(OnlineResource r) {
     1582        return OFFLINE_RESOURCES.add(r);
     1583    }
     1584
     1585    /**
     1586     * Replies the set of online resources currently offline.
     1587     * @return the set of online resources currently offline
     1588     * @since 7434
     1589     */
     1590    public static Set<OnlineResource> getOfflineResources() {
     1591        return new HashSet<>(OFFLINE_RESOURCES);
     1592    }
    15551593}
  • trunk/src/org/openstreetmap/josm/actions/CloseChangesetAction.java

    r6084 r7434  
    2323import org.openstreetmap.josm.gui.io.CloseChangesetTask;
    2424import org.openstreetmap.josm.io.ChangesetQuery;
     25import org.openstreetmap.josm.io.OnlineResource;
    2526import org.openstreetmap.josm.io.OsmServerChangesetReader;
    2627import org.openstreetmap.josm.io.OsmServerUserInfoReader;
     
    2930import org.xml.sax.SAXException;
    3031
    31 public class CloseChangesetAction extends JosmAction{
     32public class CloseChangesetAction extends JosmAction {
    3233
     34    /**
     35     * Constructs a new {@code CloseChangesetAction}.
     36     */
    3337    public CloseChangesetAction() {
    3438        super(tr("Close open changesets"),
     
    4145        );
    4246        putValue("help", ht("/Action/CloseChangeset"));
     47        setEnabled(!Main.isOffline(OnlineResource.OSM_API));
    4348
    4449    }
  • trunk/src/org/openstreetmap/josm/actions/DeleteAction.java

    r6380 r7434  
    1313import org.openstreetmap.josm.tools.Shortcut;
    1414
     15/**
     16 * Action that deletes selected objects.
     17 * @since 770
     18 */
    1519public final class DeleteAction extends JosmAction {
    1620
     21    /**
     22     * Constructs a new {@code DeleteAction}.
     23     */
    1724    public DeleteAction() {
    1825        super(tr("Delete"), "dialogs/delete", tr("Delete selected objects."),
     
    2330    @Override
    2431    public void actionPerformed(ActionEvent e) {
    25         if (!isEnabled())
    26             return;
    27         if(!Main.map.mapView.isActiveLayerVisible())
     32        if (!isEnabled() || !Main.map.mapView.isActiveLayerVisible())
    2833            return;
    2934        org.openstreetmap.josm.actions.mapmode.DeleteAction.doActionPerformed(e);
  • trunk/src/org/openstreetmap/josm/actions/HelpAction.java

    r6380 r7434  
    1414import org.openstreetmap.josm.gui.help.HelpBrowser;
    1515import org.openstreetmap.josm.gui.help.HelpUtil;
     16import org.openstreetmap.josm.io.OnlineResource;
    1617import org.openstreetmap.josm.tools.ImageProvider;
    1718
    1819/**
    1920 * Open a help browser and displays lightweight online help.
    20  *
     21 * @since 155
    2122 */
    2223public class HelpAction extends AbstractAction {
    2324
     25    /**
     26     * Constructs a new {@code HelpAction}.
     27     */
    2428    public HelpAction() {
    2529        super(tr("Help"), ImageProvider.get("help"));
    2630        putValue("toolbar", "help");
     31        setEnabled(!Main.isOffline(OnlineResource.JOSM_WEBSITE));
    2732    }
    2833
  • trunk/src/org/openstreetmap/josm/actions/HistoryInfoAction.java

    r6449 r7434  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.actions;
     3
     4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
     5import static org.openstreetmap.josm.tools.I18n.tr;
    36
    47import java.awt.event.ActionEvent;
     
    912import org.openstreetmap.josm.gui.dialogs.OsmIdSelectionDialog;
    1013import org.openstreetmap.josm.gui.history.HistoryBrowserDialogManager;
     14import org.openstreetmap.josm.io.OnlineResource;
    1115import org.openstreetmap.josm.tools.Shortcut;
    12 
    13 import static org.openstreetmap.josm.tools.I18n.tr;
    14 import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
    1516
    1617/**
     
    6162            init();
    6263        }
     64
     65        @Override
     66        public void setupDialog() {
     67            super.setupDialog();
     68            buttons.get(0).setEnabled(!Main.isOffline(OnlineResource.OSM_API));
     69        }
    6370    }
    6471}
  • trunk/src/org/openstreetmap/josm/actions/OpenLocationAction.java

    r7005 r7434  
    7373    protected void restoreUploadAddressHistory(HistoryComboBox cbHistory) {
    7474        List<String> cmtHistory = new LinkedList<>(Main.pref.getCollection(getClass().getName() + ".uploadAddressHistory", new LinkedList<String>()));
    75         // we have to reverse the history, because ComboBoxHistory will reverse it again
    76         // in addElement()
     75        // we have to reverse the history, because ComboBoxHistory will reverse it again in addElement()
    7776        //
    7877        Collections.reverse(cmtHistory);
  • trunk/src/org/openstreetmap/josm/actions/UpdateDataAction.java

    r7005 r7434  
    1515import org.openstreetmap.josm.actions.downloadtasks.DownloadTaskList;
    1616import org.openstreetmap.josm.data.osm.DataSource;
    17 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    1817import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
     18import org.openstreetmap.josm.io.OnlineResource;
    1919import org.openstreetmap.josm.tools.Shortcut;
    2020
    21 public class UpdateDataAction extends JosmAction{
     21public class UpdateDataAction extends JosmAction {
     22
     23    /**
     24     * Constructs a new {@code UpdateDataAction}.
     25     */
    2226    public UpdateDataAction() {
    2327        super(tr("Update data"),
     
    3337    /**
    3438     * Refreshes the enabled state
    35      *
    3639     */
    3740    @Override
    3841    protected void updateEnabledState() {
    39         setEnabled(getEditLayer() != null);
    40     }
    41 
    42     public void updateLayer(OsmDataLayer layer) {
    43 
     42        setEnabled(getEditLayer() != null && !Main.isOffline(OnlineResource.OSM_API));
    4443    }
    4544
  • trunk/src/org/openstreetmap/josm/actions/UpdateModifiedAction.java

    r6814 r7434  
    99import java.util.Collections;
    1010
     11import org.openstreetmap.josm.Main;
    1112import org.openstreetmap.josm.data.osm.OsmPrimitive;
     13import org.openstreetmap.josm.io.OnlineResource;
    1214import org.openstreetmap.josm.tools.Shortcut;
    1315
     
    4446    @Override
    4547    protected void updateEnabledState() {
    46         setEnabled(getCurrentDataSet() != null);
     48        setEnabled(getCurrentDataSet() != null && !Main.isOffline(OnlineResource.OSM_API));
    4749    }
    4850
  • trunk/src/org/openstreetmap/josm/actions/UpdateSelectionAction.java

    r6814 r7434  
    2222import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    2323import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
     24import org.openstreetmap.josm.io.OnlineResource;
    2425import org.openstreetmap.josm.tools.Shortcut;
    2526
     
    122123    @Override
    123124    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
    124         setEnabled(selection != null && !selection.isEmpty());
     125        setEnabled(selection != null && !selection.isEmpty() && !Main.isOffline(OnlineResource.OSM_API));
    125126    }
    126127
  • trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java

    r7217 r7434  
    129129    }
    130130
     131    /**
     132     * Invoked when the action occurs.
     133     * @param e Action event
     134     */
    131135    public static void doActionPerformed(ActionEvent e) {
    132         if(!Main.map.mapView.isActiveLayerDrawable())
     136        if (!Main.map.mapView.isActiveLayerDrawable())
    133137            return;
    134138        boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
     
    149153    }
    150154
    151     @Override public void mouseDragged(MouseEvent e) {
     155    @Override
     156    public void mouseDragged(MouseEvent e) {
    152157        mouseMoved(e);
    153158    }
     
    157162     * @param e The mouse event that has been captured
    158163     */
    159     @Override public void mouseMoved(MouseEvent e) {
     164    @Override
     165    public void mouseMoved(MouseEvent e) {
    160166        oldEvent = e;
    161167        giveUserFeedback(e);
     
    245251        Main.map.mapView.setNewCursor(parameters.mode.cursor(), this);
    246252    }
     253
    247254    /**
    248255     * Gives the user feedback for the action he/she is about to do. Currently
     
    274281     * position.
    275282     */
    276     @Override public void mouseReleased(MouseEvent e) {
     283    @Override
     284    public void mouseReleased(MouseEvent e) {
    277285        if (e.getButton() != MouseEvent.BUTTON1)
    278286            return;
     
    293301    }
    294302
    295     @Override public String getModeHelpText() {
     303    @Override
     304    public String getModeHelpText() {
    296305        return tr("Click to delete. Shift: delete way segment. Alt: do not delete unused nodes when deleting a way. Ctrl: delete referring objects.");
    297306    }
    298307
    299     @Override public boolean layerIsSupported(Layer l) {
     308    @Override
     309    public boolean layerIsSupported(Layer l) {
    300310        return l instanceof OsmDataLayer;
    301311    }
     
    391401    @Override
    392402    public void modifiersChanged(int modifiers) {
    393         if(oldEvent == null)
    394             return;
    395         // We don't have a mouse event, so we pass the old mouse event but the
    396         // new modifiers.
     403        if (oldEvent == null)
     404            return;
     405        // We don't have a mouse event, so we pass the old mouse event but the new modifiers.
    397406        giveUserFeedback(oldEvent, modifiers);
    398407    }
  • trunk/src/org/openstreetmap/josm/actions/relation/DownloadMembersAction.java

    r6336 r7434  
    1212import org.openstreetmap.josm.data.osm.Relation;
    1313import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationTask;
     14import org.openstreetmap.josm.io.OnlineResource;
    1415import org.openstreetmap.josm.tools.ImageProvider;
    1516import org.openstreetmap.josm.tools.Predicate;
     
    3132        putValue("help", ht("/Dialog/RelationList#DownloadMembers"));
    3233    }
    33    
     34
    3435    @Override
    3536    public void actionPerformed(ActionEvent e) {
     
    4748        updateEnabledState();
    4849    }
     50
     51    @Override
     52    protected void updateEnabledState() {
     53        setEnabled(!relations.isEmpty() && !Main.isOffline(OnlineResource.OSM_API));
     54    }
    4955}
  • trunk/src/org/openstreetmap/josm/actions/relation/DownloadSelectedIncompleteMembersAction.java

    r7005 r7434  
    1313import org.openstreetmap.josm.data.osm.Relation;
    1414import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
     15import org.openstreetmap.josm.io.OnlineResource;
    1516import org.openstreetmap.josm.tools.ImageProvider;
    1617import org.openstreetmap.josm.tools.Predicate;
     
    6364        updateEnabledState();
    6465    }
     66
     67    @Override
     68    protected void updateEnabledState() {
     69        setEnabled(!relations.isEmpty() && !Main.isOffline(OnlineResource.OSM_API));
     70    }
    6571}
  • trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java

    r6248 r7434  
    1515import org.openstreetmap.josm.gui.ExceptionDialogUtil;
    1616import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
     17import org.openstreetmap.josm.io.OnlineResource;
    1718import org.openstreetmap.josm.io.OsmApi;
    1819import org.openstreetmap.josm.io.OsmApiInitializationException;
     
    2526        OsmApi api = OsmApi.getOsmApi();
    2627        try {
     28            if (Main.isOffline(OnlineResource.OSM_API)) {
     29                return false;
     30            }
    2731            // FIXME: this should run asynchronously and a progress monitor
    2832            // should be displayed.
     
    4044                    return false;
    4145            }
    42         } catch(OsmTransferCanceledException e){
     46        } catch (OsmTransferCanceledException e) {
    4347            return false;
    4448        } catch (OsmApiInitializationException e) {
  • trunk/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java

    r7248 r7434  
    1414import java.util.Set;
    1515import java.util.TreeSet;
     16
    1617import org.openstreetmap.josm.Main;
    1718import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryPreferenceEntry;
    1819import org.openstreetmap.josm.io.CachedFile;
     20import org.openstreetmap.josm.io.OfflineAccessException;
     21import org.openstreetmap.josm.io.OnlineResource;
    1922import org.openstreetmap.josm.io.imagery.ImageryReader;
    2023import org.xml.sax.SAXException;
     
    3437        Main.getJOSMWebsite()+"/maps"
    3538    };
     39
     40    /**
     41     * Returns the list of imagery layers sites.
     42     * @return the list of imagery layers sites
     43     * @since 7434
     44     */
     45    public static Collection<String> getImageryLayersSites() {
     46        return Main.pref.getCollection("imagery.layers.sites", Arrays.asList(DEFAULT_LAYER_SITES));
     47    }
    3648
    3749    private ImageryLayerInfo() {
     
    7688        defaultLayers.clear();
    7789        defaultLayerIds.clear();
    78         for (String source : Main.pref.getCollection("imagery.layers.sites", Arrays.asList(DEFAULT_LAYER_SITES))) {
    79             if (clearCache) {
     90        for (String source : getImageryLayersSites()) {
     91            boolean online = true;
     92            try {
     93                OnlineResource.JOSM_WEBSITE.checkOfflineAccess(source, Main.getJOSMWebsite());
     94            } catch (OfflineAccessException e) {
     95                Main.warn(e.getMessage());
     96                online = false;
     97            }
     98            if (clearCache && online) {
    8099                CachedFile.cleanup(source);
    81100            }
     
    96115        buildIdMap(layers, layerIds);
    97116    }
    98    
     117
    99118    /**
    100119     * Build the mapping of unique ids to {@link ImageryInfo}s.
     
    120139        }
    121140    }
    122    
     141
    123142    /**
    124143     * Update user entries according to the list of default entries.
     
    179198        }
    180199        Main.pref.putCollection("imagery.layers.addedIds", newAddedIds);
    181        
     200
    182201        // automatically update user entries with same id as a default entry
    183202        for (int i=0; i<layers.size(); i++) {
     
    192211            }
    193212        }
    194        
     213
    195214        if (changed) {
    196215            save();
     
    202221        return isSimilar(iiA.getUrl(), iiB.getUrl());
    203222    }
    204    
     223
    205224    // some additional checks to respect extended URLs in preferences (legacy workaround)
    206225    private boolean isSimilar(String a, String b) {
    207226        return Objects.equals(a, b) || (a != null && b != null && !a.isEmpty() && !b.isEmpty() && (a.contains(b) || b.contains(a)));
    208227    }
    209    
     228
    210229    public void add(ImageryInfo info) {
    211230        layers.add(info);
     
    244263        Collections.sort(instance.layers);
    245264    }
    246    
     265
    247266    /**
    248267     * Get unique id for ImageryInfo.
    249      * 
     268     *
    250269     * This takes care, that no id is used twice (due to a user error)
    251270     * @param info the ImageryInfo to look up
  • trunk/src/org/openstreetmap/josm/gui/ExceptionDialogUtil.java

    r7187 r7434  
    2020import org.openstreetmap.josm.io.IllegalDataException;
    2121import org.openstreetmap.josm.io.MissingOAuthAccessTokenException;
     22import org.openstreetmap.josm.io.OfflineAccessException;
    2223import org.openstreetmap.josm.io.OsmApi;
    2324import org.openstreetmap.josm.io.OsmApiException;
     
    154155     * @param e the exception
    155156     */
    156 
    157157    public static void explainNestedIllegalDataException(OsmTransferException e) {
    158158        HelpAwareOptionPane.showOptionDialog(
     
    166166
    167167    /**
     168     * Explains a {@link OfflineAccessException} which has caused an {@link OsmTransferException}.
     169     * This is most likely happening when JOSM tries to access OSM API or JOSM website while in offline mode.
     170     *
     171     * @param e the exception
     172     * @since 7434
     173     */
     174    public static void explainNestedOfflineAccessException(OsmTransferException e) {
     175        HelpAwareOptionPane.showOptionDialog(
     176                Main.parent,
     177                ExceptionUtil.explainOfflineAccessException(e),
     178                tr("Offline mode"),
     179                JOptionPane.ERROR_MESSAGE,
     180                ht("/ErrorMessages#OfflineAccessException")
     181        );
     182    }
     183
     184    /**
    168185     * Explains a {@link InvocationTargetException }
    169186     *
    170187     * @param e the exception
    171188     */
    172 
    173189    public static void explainNestedInvocationTargetException(Exception e) {
    174190        InvocationTargetException ex = getNestedException(e, InvocationTargetException.class);
     
    435451            return;
    436452        }
     453        if (getNestedException(e, OfflineAccessException.class) != null) {
     454            explainNestedOfflineAccessException(e);
     455            return;
     456        }
    437457        if (e instanceof OsmApiInitializationException) {
    438458            explainOsmApiInitializationException((OsmApiInitializationException) e);
  • trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java

    r7407 r7434  
    3030import javax.swing.UIManager;
    3131
     32import org.openstreetmap.josm.Main;
    3233import org.openstreetmap.josm.gui.help.HelpBrowser;
    3334import org.openstreetmap.josm.gui.help.HelpUtil;
    3435import org.openstreetmap.josm.gui.util.GuiHelper;
    3536import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
     37import org.openstreetmap.josm.io.OnlineResource;
    3638import org.openstreetmap.josm.tools.GBC;
    3739import org.openstreetmap.josm.tools.ImageProvider;
     
    642644            putValue(NAME, tr("Help"));
    643645            putValue(SMALL_ICON, ImageProvider.get("help"));
    644         }
    645 
    646         @Override public void actionPerformed(ActionEvent e) {
     646            setEnabled(!Main.isOffline(OnlineResource.JOSM_WEBSITE));
     647        }
     648
     649        @Override
     650        public void actionPerformed(ActionEvent e) {
    647651            HelpBrowser.setUrlForHelpTopic(helpTopic);
    648652        }
  • trunk/src/org/openstreetmap/josm/gui/GettingStarted.java

    r7082 r7434  
    3030import org.openstreetmap.josm.gui.widgets.JosmEditorPane;
    3131import org.openstreetmap.josm.io.CacheCustomContent;
     32import org.openstreetmap.josm.io.OnlineResource;
    3233import org.openstreetmap.josm.tools.LanguageInfo;
    3334import org.openstreetmap.josm.tools.OpenBrowser;
     
    9596        }
    9697
     98        @Override
     99        protected void checkOfflineAccess() {
     100            OnlineResource.JOSM_WEBSITE.checkOfflineAccess(new WikiReader().getBaseUrlWiki(), Main.getJOSMWebsite());
     101        }
     102
    97103        /**
    98104         * Additionally check if JOSM has been updated and refresh MOTD
     
    151157                }
    152158
    153                 EventQueue.invokeLater(new Runnable() {
    154                     @Override
    155                     public void run() {
    156                         lg.setText(fixImageLinks(content));
    157                     }
    158                 });
     159                if (content != null) {
     160                    EventQueue.invokeLater(new Runnable() {
     161                        @Override
     162                        public void run() {
     163                            lg.setText(fixImageLinks(content));
     164                        }
     165                    });
     166                }
    159167            }
    160168        }, "MOTD-Loader");
  • trunk/src/org/openstreetmap/josm/gui/JosmUserIdentityManager.java

    r7081 r7434  
    1414import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
    1515import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
     16import org.openstreetmap.josm.io.OnlineResource;
    1617import org.openstreetmap.josm.io.OsmApi;
    1718import org.openstreetmap.josm.io.OsmServerUserInfoReader;
     
    6162        if (instance == null) {
    6263            instance = new JosmUserIdentityManager();
    63             if (OsmApi.isUsingOAuth() && OAuthAccessTokenHolder.getInstance().containsAccessToken()) {
     64            if (OsmApi.isUsingOAuth() && OAuthAccessTokenHolder.getInstance().containsAccessToken() &&
     65                    !Main.isOffline(OnlineResource.OSM_API)) {
    6466                try {
    6567                    instance.initFromOAuth(Main.parent);
  • trunk/src/org/openstreetmap/josm/gui/MainApplication.java

    r7383 r7434  
    2727import java.security.cert.CertificateException;
    2828import java.util.ArrayList;
     29import java.util.Arrays;
    2930import java.util.Collection;
    3031import java.util.HashMap;
     
    5455import org.openstreetmap.josm.io.DefaultProxySelector;
    5556import org.openstreetmap.josm.io.MessageNotifier;
     57import org.openstreetmap.josm.io.OnlineResource;
    5658import org.openstreetmap.josm.io.auth.CredentialsManager;
    5759import org.openstreetmap.josm.io.auth.DefaultAuthenticator;
     
    8789        mainFrame.setJMenuBar(menu);
    8890        geometry.applySafe(mainFrame);
    89         LinkedList<Image> l = new LinkedList<>();
     91        List<Image> l = new LinkedList<>();
    9092        l.add(ImageProvider.get("logo_16x16x32").getImage());
    9193        l.add(ImageProvider.get("logo_16x16x8").getImage());
     
    131133                "\t--version                                 "+tr("Displays the JOSM version and exits")+"\n\n"+
    132134                "\t--debug                                   "+tr("Print debugging messages to console")+"\n\n"+
     135                "\t--offline=<osm_api|josm_website|all>      "+tr("Disable access to the given resource(s), separated by comma")+"\n\n"+
    133136                tr("options provided as Java system properties")+":\n"+
    134137                "\t-Djosm.home="+tr("/PATH/TO/JOSM/FOLDER/         ")+tr("Change the folder for all user settings")+"\n\n"+
     
    154157     */
    155158    public enum Option {
    156         /** --help|-h                                 Show this help */
     159        /** --help|-h                                  Show this help */
    157160        HELP(false),
    158         /** --version                                 Displays the JOSM version and exits */
     161        /** --version                                  Displays the JOSM version and exits */
    159162        VERSION(false),
    160         /** --debug                                   Print debugging messages to console */
     163        /** --debug                                    Print debugging messages to console */
    161164        DEBUG(false),
    162         /** --trace                                   Print detailed debugging messages to console */
     165        /** --trace                                    Print detailed debugging messages to console */
    163166        TRACE(false),
    164         /** --language=&lt;language&gt;               Set the language */
     167        /** --language=&lt;language&gt;                Set the language */
    165168        LANGUAGE(true),
    166         /** --reset-preferences                       Reset the preferences to default */
     169        /** --reset-preferences                        Reset the preferences to default */
    167170        RESET_PREFERENCES(false),
    168         /** --load-preferences=&lt;url-to-xml&gt;     Changes preferences according to the XML file */
     171        /** --load-preferences=&lt;url-to-xml&gt;      Changes preferences according to the XML file */
    169172        LOAD_PREFERENCES(true),
    170         /** --set=&lt;key&gt;=&lt;value&gt;           Set preference key to value */
     173        /** --set=&lt;key&gt;=&lt;value&gt;            Set preference key to value */
    171174        SET(true),
    172         /** --geometry=widthxheight(+|-)x(+|-)y       Standard unix geometry argument */
     175        /** --geometry=widthxheight(+|-)x(+|-)y        Standard unix geometry argument */
    173176        GEOMETRY(true),
    174         /** --no-maximize                             Do not launch in maximized mode */
     177        /** --no-maximize                              Do not launch in maximized mode */
    175178        NO_MAXIMIZE(false),
    176         /** --maximize                                Launch in maximized mode */
     179        /** --maximize                                 Launch in maximized mode */
    177180        MAXIMIZE(false),
    178         /** --download=minlat,minlon,maxlat,maxlon    Download the bounding box <br>
    179          *  --download=&lt;URL&gt;                    Download the location at the URL (with lat=x&amp;lon=y&amp;zoom=z) <br>
    180          *  --download=&lt;filename&gt;               Open a file (any file type that can be opened with File/Open) */
     181        /** --download=minlat,minlon,maxlat,maxlon     Download the bounding box <br>
     182         *  --download=&lt;URL&gt;                     Download the location at the URL (with lat=x&amp;lon=y&amp;zoom=z) <br>
     183         *  --download=&lt;filename&gt;                Open a file (any file type that can be opened with File/Open) */
    181184        DOWNLOAD(true),
    182         /** --downloadgps=minlat,minlon,maxlat,maxlon Download the bounding box as raw GPS <br>
    183          *  --downloadgps=&lt;URL&gt;                 Download the location at the URL (with lat=x&amp;lon=y&amp;zoom=z) as raw GPS */
     185        /** --downloadgps=minlat,minlon,maxlat,maxlon  Download the bounding box as raw GPS <br>
     186         *  --downloadgps=&lt;URL&gt;                  Download the location at the URL (with lat=x&amp;lon=y&amp;zoom=z) as raw GPS */
    184187        DOWNLOADGPS(true),
    185         /** --selection=&lt;searchstring&gt;          Select with the given search */
    186         SELECTION(true);
     188        /** --selection=&lt;searchstring&gt;           Select with the given search */
     189        SELECTION(true),
     190        /** --offline=&lt;osm_api|josm_website|all&gt; Disable access to the given resource(s), delimited by comma */
     191        OFFLINE(true);
    187192
    188193        private String name;
     
    284289        } catch (IllegalArgumentException e) {
    285290            System.exit(1);
     291            return;
    286292        }
    287293
     
    347353        Main.pref.updateSystemProperties();
    348354
     355        processOffline(args);
     356
    349357        FontsManager.initialize();
    350        
     358
    351359        final JFrame mainFrame = new JFrame(tr("Java OpenStreetMap Editor"));
    352360        Main.parent = mainFrame;
     
    466474            info("Enabled EDT checker, wrongful access to gui from non EDT thread will be printed to console");
    467475            RepaintManager.setCurrentManager(new CheckThreadViolationRepaintManager());
     476        }
     477    }
     478
     479    private static void processOffline(Map<Option, Collection<String>> args) {
     480        if (args.containsKey(Option.OFFLINE)) {
     481            for (String s : args.get(Option.OFFLINE).iterator().next().split(",")) {
     482                try {
     483                    Main.setOffline(OnlineResource.valueOf(s.toUpperCase()));
     484                } catch (IllegalArgumentException e) {
     485                    Main.error(tr("''{0}'' is not a valid value for argument ''{1}''. Possible values are {2}, possibly delimited by commas.",
     486                            s.toUpperCase(), Option.OFFLINE.getName(), Arrays.toString(OnlineResource.values())));
     487                    System.exit(1);
     488                    return;
     489                }
     490            }
     491            Set<OnlineResource> offline = Main.getOfflineResources();
     492            if (!offline.isEmpty()) {
     493                Main.warn(trn("JOSM is running in offline mode. This resource will not be available: {0}",
     494                        "JOSM is running in offline mode. These resources will not be available: {0}",
     495                        offline.size(), offline.size() == 1 ? offline.iterator().next() : Arrays.toString(offline.toArray())));
     496            }
    468497        }
    469498    }
  • trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java

    r7005 r7434  
    5252import org.openstreetmap.josm.gui.io.CloseChangesetTask;
    5353import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     54import org.openstreetmap.josm.gui.util.GuiHelper;
    5455import org.openstreetmap.josm.gui.widgets.ListPopupMenu;
    5556import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
     57import org.openstreetmap.josm.io.OnlineResource;
    5658import org.openstreetmap.josm.tools.BugReportExceptionHandler;
    5759import org.openstreetmap.josm.tools.ImageProvider;
     
    363365
    364366        protected void updateEnabledState() {
    365             setEnabled(getCurrentChangesetList().getSelectedIndices().length > 0);
     367            setEnabled(getCurrentChangesetList().getSelectedIndices().length > 0 && !Main.isOffline(OnlineResource.OSM_API));
    366368        }
    367369
     
    486488            Set<Integer> sel = model.getSelectedChangesetIds();
    487489            final Set<Integer> toDownload = new HashSet<>();
    488             ChangesetCache cc = ChangesetCache.getInstance();
    489             for (int id: sel) {
    490                 if (!cc.contains(id)) {
    491                     toDownload.add(id);
     490            if (!Main.isOffline(OnlineResource.OSM_API)) {
     491                ChangesetCache cc = ChangesetCache.getInstance();
     492                for (int id: sel) {
     493                    if (!cc.contains(id)) {
     494                        toDownload.add(id);
     495                    }
    492496                }
    493497            }
     
    506510                @Override
    507511                public void run() {
    508                     // first, wait for the download task to finish, if a download
    509                     // task was launched
     512                    // first, wait for the download task to finish, if a download task was launched
    510513                    if (future != null) {
    511514                        try {
     
    521524                    if (task != null) {
    522525                        if (task.isCanceled())
    523                             // don't launch the changeset manager if the download task
    524                             // was canceled
     526                            // don't launch the changeset manager if the download task was canceled
    525527                            return;
    526528                        if (task.isFailed()) {
     
    529531                    }
    530532                    // launch the task
    531                     launchChangesetManager(toDownload);
     533                    GuiHelper.runInEDT(new Runnable() {
     534                        @Override
     535                        public void run() {
     536                            launchChangesetManager(toDownload);
     537                        }
     538                    });
    532539                }
    533540            };
  • trunk/src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java

    r7005 r7434  
    4242import org.openstreetmap.josm.gui.history.HistoryBrowserDialogManager;
    4343import org.openstreetmap.josm.gui.history.HistoryLoadTask;
     44import org.openstreetmap.josm.io.OnlineResource;
    4445import org.openstreetmap.josm.tools.ImageProvider;
    4546import org.openstreetmap.josm.tools.InputMapUtils;
     
    286287
    287288        protected void updateEnabledState() {
    288             setEnabled(historyTable.getSelectedRowCount() > 0);
     289            setEnabled(historyTable.getSelectedRowCount() > 0 && !Main.isOffline(OnlineResource.OSM_API));
    289290        }
    290291
  • trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManager.java

    r7005 r7434  
    4949import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
    5050import org.openstreetmap.josm.io.ChangesetQuery;
     51import org.openstreetmap.josm.io.OnlineResource;
    5152import org.openstreetmap.josm.tools.ImageProvider;
    5253import org.openstreetmap.josm.tools.WindowGeometry;
     
    364365            putValue(SMALL_ICON, ImageProvider.get("dialogs","search"));
    365366            putValue(SHORT_DESCRIPTION, tr("Launch the dialog for querying changesets"));
     367            setEnabled(!Main.isOffline(OnlineResource.OSM_API));
    366368        }
    367369
     
    476478
    477479        protected void updateEnabledState() {
    478             setEnabled(model.hasSelectedChangesets());
     480            setEnabled(model.hasSelectedChangesets() && !Main.isOffline(OnlineResource.OSM_API));
    479481        }
    480482
     
    504506
    505507        protected void updateEnabledState() {
    506             setEnabled(model.hasSelectedChangesets());
     508            setEnabled(model.hasSelectedChangesets() && !Main.isOffline(OnlineResource.OSM_API));
    507509        }
    508510
     
    532534            putValue(SMALL_ICON, ImageProvider.get("dialogs/changeset", "downloadchangeset"));
    533535            putValue(SHORT_DESCRIPTION, tr("Download my changesets from the OSM server (max. 100 changesets)"));
     536            setEnabled(!Main.isOffline(OnlineResource.OSM_API));
    534537        }
    535538
  • trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDetailPanel.java

    r7299 r7434  
    4040import org.openstreetmap.josm.gui.widgets.JosmTextArea;
    4141import org.openstreetmap.josm.gui.widgets.JosmTextField;
     42import org.openstreetmap.josm.io.OnlineResource;
    4243import org.openstreetmap.josm.tools.ImageProvider;
    4344import org.openstreetmap.josm.tools.date.DateUtils;
     
    345346
    346347        public void initProperties(Changeset cs) {
    347             if (cs == null) {
    348                 setEnabled(false);
    349                 return;
    350             } else {
    351                 setEnabled(true);
    352             }
     348            setEnabled(cs != null && !Main.isOffline(OnlineResource.OSM_API));
    353349        }
    354350    }
  • trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/SingleChangesetDownloadPanel.java

    r6603 r7434  
    2020import org.openstreetmap.josm.gui.widgets.ChangesetIdTextField;
    2121import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
     22import org.openstreetmap.josm.io.OnlineResource;
    2223
    2324/**
     
    9899
    99100        protected void updateEnabledState() {
    100             setEnabled(tfChangesetId.readIds());
     101            setEnabled(tfChangesetId.readIds() && !Main.isOffline(OnlineResource.OSM_API));
    101102        }
    102103
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java

    r7128 r7434  
    8383import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
    8484import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
     85import org.openstreetmap.josm.io.OnlineResource;
    8586import org.openstreetmap.josm.tools.CheckParameterUtil;
    8687import org.openstreetmap.josm.tools.ImageProvider;
     
    212213                }
    213214        );
    214         registerCopyPasteAction(tagEditorPanel.getPasteAction(), 
     215        registerCopyPasteAction(tagEditorPanel.getPasteAction(),
    215216                "PASTE_TAGS",
    216217                Shortcut.registerShortcut("system:pastestyle", tr("Edit: {0}", tr("Paste Tags")), KeyEvent.VK_V, Shortcut.CTRL_SHIFT).getKeyStroke());
     
    14751476
    14761477        protected void updateEnabledState() {
    1477             setEnabled(memberTableModel.hasIncompleteMembers());
     1478            setEnabled(memberTableModel.hasIncompleteMembers() && !Main.isOffline(OnlineResource.OSM_API));
    14781479        }
    14791480
     
    15071508
    15081509        protected void updateEnabledState() {
    1509             setEnabled(memberTableModel.hasIncompleteSelectedMembers());
     1510            setEnabled(memberTableModel.hasIncompleteSelectedMembers() && !Main.isOffline(OnlineResource.OSM_API));
    15101511        }
    15111512
  • trunk/src/org/openstreetmap/josm/gui/download/DownloadDialog.java

    r7005 r7434  
    3939import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
    4040import org.openstreetmap.josm.gui.help.HelpUtil;
     41import org.openstreetmap.josm.io.OnlineResource;
    4142import org.openstreetmap.josm.plugins.PluginHandler;
    4243import org.openstreetmap.josm.tools.GBC;
     
    103104
    104105        slippyMapChooser = new SlippyMapChooser();
    105        
     106
    106107        // predefined download selections
    107108        downloadSelections.add(slippyMapChooser);
     
    305306        }
    306307    }
    307    
     308
    308309    /**
    309310     * Remembers the current settings in the download dialog.
     
    349350        }
    350351    }
    351    
     352
    352353    /**
    353354     * Returns the previously saved bounding box from preferences.
     
    444445            putValue(SMALL_ICON, ImageProvider.get("download"));
    445446            putValue(SHORT_DESCRIPTION, tr("Click to download the currently selected area"));
     447            setEnabled(!Main.isOffline(OnlineResource.OSM_API));
    446448        }
    447449
  • trunk/src/org/openstreetmap/josm/gui/download/DownloadObjectDialog.java

    r6448 r7434  
    1616import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    1717import org.openstreetmap.josm.gui.dialogs.OsmIdSelectionDialog;
     18import org.openstreetmap.josm.io.OnlineResource;
    1819
    1920/**
     
    4950    }
    5051
     52    @Override
     53    public void setupDialog() {
     54        super.setupDialog();
     55        buttons.get(0).setEnabled(!Main.isOffline(OnlineResource.OSM_API));
     56    }
     57
     58    @Override
    5159    protected Collection<Component> getComponentsBeforeHelp() {
    5260        newLayer.setToolTipText(tr("Select if the data should be downloaded into a new layer"));
  • trunk/src/org/openstreetmap/josm/gui/help/ContextSensitiveHelpAction.java

    r6084 r7434  
    22package org.openstreetmap.josm.gui.help;
    33
     4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
     5import static org.openstreetmap.josm.tools.I18n.tr;
     6
    47import java.awt.event.ActionEvent;
    5 import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
    68
    79import javax.swing.AbstractAction;
    8 import static org.openstreetmap.josm.tools.I18n.tr;
    910
     11import org.openstreetmap.josm.Main;
     12import org.openstreetmap.josm.io.OnlineResource;
    1013import org.openstreetmap.josm.tools.ImageProvider;
    1114
     
    1316 * This is the standard help action to be used with help buttons for
    1417 * context sensitive help
    15  *
     18 * @since 2289
    1619 */
    1720public class ContextSensitiveHelpAction extends AbstractAction {
    1821
    19     /** the help topic */
    2022    private String helpTopic;
    2123
    2224    /**
    23      * Sets the help topic
     25     * Sets the help topic.
    2426     *
    2527     * @param relativeHelpTopic the relative help topic
     
    3234
    3335    /**
    34      * Creates a help topic for the root help topic
    35      *
     36     * Constructs a new {@code ContextSensitiveHelpAction} for the root help topic.
    3637     */
    3738    public ContextSensitiveHelpAction() {
     
    4041
    4142    /**
    42      *
    43      * @param helpTopic
     43     * Constructs a new {@code ContextSensitiveHelpAction} for a given help topic.
     44     * @param helpTopic The help topic
    4445     */
    4546    public ContextSensitiveHelpAction(String helpTopic) {
     
    4849        putValue(SMALL_ICON, ImageProvider.get("help"));
    4950        this.helpTopic = helpTopic;
     51        setEnabled(!Main.isOffline(OnlineResource.JOSM_WEBSITE));
    5052    }
    5153
  • trunk/src/org/openstreetmap/josm/gui/preferences/SourceEditor.java

    r7248 r7434  
    8787import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    8888import org.openstreetmap.josm.gui.util.FileFilterAllFiles;
     89import org.openstreetmap.josm.gui.util.GuiHelper;
    8990import org.openstreetmap.josm.gui.util.TableHelper;
    9091import org.openstreetmap.josm.gui.widgets.JFileChooserManager;
    9192import org.openstreetmap.josm.gui.widgets.JosmTextField;
    9293import org.openstreetmap.josm.io.CachedFile;
     94import org.openstreetmap.josm.io.OnlineResource;
    9395import org.openstreetmap.josm.io.OsmTransferException;
    9496import org.openstreetmap.josm.tools.GBC;
     
    10411043            this.url = url;
    10421044            this.sourceProviders = sourceProviders;
     1045            setEnabled(!Main.isOffline(OnlineResource.JOSM_WEBSITE));
    10431046        }
    10441047
     
    12561259            String emsg = e.getMessage() != null ? e.getMessage() : e.toString();
    12571260            emsg = emsg.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
    1258             String msg = tr(getStr(I18nString.FAILED_TO_LOAD_SOURCES_FROM), url, emsg);
    1259 
    1260             HelpAwareOptionPane.showOptionDialog(
    1261                     Main.parent,
    1262                     msg,
    1263                     tr("Error"),
    1264                     JOptionPane.ERROR_MESSAGE,
    1265                     ht(getStr(I18nString.FAILED_TO_LOAD_SOURCES_FROM_HELP_TOPIC))
    1266                     );
     1261            final String msg = tr(getStr(I18nString.FAILED_TO_LOAD_SOURCES_FROM), url, emsg);
     1262
     1263            GuiHelper.runInEDT(new Runnable() {
     1264                @Override
     1265                public void run() {
     1266                    HelpAwareOptionPane.showOptionDialog(
     1267                            Main.parent,
     1268                            msg,
     1269                            tr("Error"),
     1270                            JOptionPane.ERROR_MESSAGE,
     1271                            ht(getStr(I18nString.FAILED_TO_LOAD_SOURCES_FROM_HELP_TOPIC))
     1272                            );
     1273                }
     1274            });
    12671275        }
    12681276
  • trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreference.java

    r7021 r7434  
    5050import org.openstreetmap.josm.gui.widgets.JosmTextField;
    5151import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
     52import org.openstreetmap.josm.io.OfflineAccessException;
     53import org.openstreetmap.josm.io.OnlineResource;
    5254import org.openstreetmap.josm.plugins.PluginDownloadTask;
    5355import org.openstreetmap.josm.plugins.PluginInformation;
     
    114116        return sb.toString();
    115117    }
    116    
     118
    117119    /**
    118120     * Notifies user about result of a finished plugin download task.
     
    313315    }
    314316
     317    private static Collection<String> getOnlinePluginSites() {
     318        Collection<String> pluginSites = new ArrayList<>(Main.pref.getPluginSites());
     319        for (Iterator<String> it = pluginSites.iterator(); it.hasNext();) {
     320            try {
     321                OnlineResource.JOSM_WEBSITE.checkOfflineAccess(it.next(), Main.getJOSMWebsite());
     322            } catch (OfflineAccessException ex) {
     323                Main.warn(ex.getMessage());
     324                it.remove();
     325            }
     326        }
     327        return pluginSites;
     328    }
     329
    315330    /**
    316331     * The action for downloading the list of available plugins
    317      *
    318332     */
    319333    class DownloadAvailablePluginsAction extends AbstractAction {
     
    327341        @Override
    328342        public void actionPerformed(ActionEvent e) {
    329             final ReadRemotePluginInformationTask task = new ReadRemotePluginInformationTask(Main.pref.getPluginSites());
     343            Collection<String> pluginSites = getOnlinePluginSites();
     344            if (pluginSites.isEmpty()) {
     345                return;
     346            }
     347            final ReadRemotePluginInformationTask task = new ReadRemotePluginInformationTask(pluginSites);
    330348            Runnable continuation = new Runnable() {
    331349                @Override
     
    345363            Main.worker.submit(continuation);
    346364        }
    347     }
    348 
    349     /**
    350      * The action for downloading the list of available plugins
    351      *
     365
     366    }
     367
     368    /**
     369     * The action for updating the list of selected plugins
    352370     */
    353371    class UpdateSelectedPluginsAction extends AbstractAction {
     
    387405                    );
    388406            // the async task for downloading plugin information
    389             final ReadRemotePluginInformationTask pluginInfoDownloadTask = new ReadRemotePluginInformationTask(Main.pref.getPluginSites());
     407            final ReadRemotePluginInformationTask pluginInfoDownloadTask = new ReadRemotePluginInformationTask(getOnlinePluginSites());
    390408
    391409            // to be run asynchronously after the plugin download
  • trunk/src/org/openstreetmap/josm/io/CacheCustomContent.java

    r7082 r7434  
    8080    }
    8181
     82    private boolean needsUpdate() {
     83        if (isOffline()) {
     84            return false;
     85        }
     86        return Main.pref.getInteger("cache." + ident, 0) + updateInterval < System.currentTimeMillis()/1000
     87                || !isCacheValid();
     88    }
     89
     90    private boolean isOffline() {
     91        try {
     92            checkOfflineAccess();
     93            return false;
     94        } catch (OfflineAccessException e) {
     95            return true;
     96        }
     97    }
     98
     99    protected void checkOfflineAccess() {
     100        // To be overriden by subclasses
     101    }
     102
    82103    /**
    83104     * Updates data if required
     
    85106     */
    86107    public byte[] updateIfRequired() throws T {
    87         if (Main.pref.getInteger("cache." + ident, 0) + updateInterval < System.currentTimeMillis()/1000
    88                 || !isCacheValid())
     108        if (needsUpdate())
    89109            return updateForce();
    90110        return getData();
     
    96116     */
    97117    public String updateIfRequiredString() throws T {
    98         if (Main.pref.getInteger("cache." + ident, 0) + updateInterval < System.currentTimeMillis()/1000
    99                 || !isCacheValid())
     118        if (needsUpdate())
    100119            return updateForceString();
    101120        return getDataString();
     
    138157     */
    139158    public String getDataString() throws T {
    140         return new String(getData(), StandardCharsets.UTF_8);
     159        byte[] array = getData();
     160        if (array == null) {
     161            return null;
     162        }
     163        return new String(array, StandardCharsets.UTF_8);
    141164    }
    142165
    143166    /**
    144      * Tries to load the data using the given ident from disk. If this fails, data will be updated
     167     * Tries to load the data using the given ident from disk. If this fails, data will be updated, unless run in offline mode
    145168     */
    146169    private void loadFromDisk() throws T {
     
    149172            input.read(this.data);
    150173        } catch (IOException e) {
    151             this.data = updateForce();
     174            if (!isOffline()) {
     175                this.data = updateForce();
     176            }
    152177        }
    153178    }
     
    166191
    167192    /**
    168      * Flushes the data from memory. Class automatically reloads it from disk or updateData() if
    169      * required
     193     * Flushes the data from memory. Class automatically reloads it from disk or updateData() if required
    170194     */
    171195    public void flushData() {
  • trunk/src/org/openstreetmap/josm/io/CachedFile.java

    r7282 r7434  
    2424
    2525import org.openstreetmap.josm.Main;
     26import org.openstreetmap.josm.tools.CheckParameterUtil;
    2627import org.openstreetmap.josm.tools.Pair;
    2728import org.openstreetmap.josm.tools.Utils;
     
    2930/**
    3031 * Downloads a file and caches it on disk in order to reduce network load.
    31  * 
     32 *
    3233 * Supports URLs, local files, and a custom scheme (<code>resource:</code>) to get
    3334 * resources from the current *.jar file. (Local caching is only done for URLs.)
     
    4950         * consider the cache stale and try to download the file again.
    5051         */
    51         MaxAge, 
     52        MaxAge,
    5253        /**
    5354         * Similar to MaxAge, considers the cache stale when a certain age is
     
    5657         * as a full download.
    5758         */
    58         IfModifiedSince 
     59        IfModifiedSince
    5960    }
    6061    protected String name;
     
    6364    protected String httpAccept;
    6465    protected CachingStrategy cachingStrategy;
    65    
     66
    6667    protected File cacheFile = null;
    6768    boolean initialized = false;
     
    9899        return this;
    99100    }
    100    
     101
    101102    /**
    102103     * Set maximum age of cache file. Only applies to URLs.
     
    201202                cacheFile = checkLocal(url);
    202203            }
    203         } catch (java.net.MalformedURLException e) {
     204        } catch (MalformedURLException e) {
    204205            if (name.startsWith("resource://")) {
    205206                return null;
     
    211212        }
    212213        if (cacheFile == null)
    213             throw new IOException();
     214            throw new IOException("Unable to get cache file for "+name);
    214215        return cacheFile;
    215216    }
    216    
     217
    217218    /**
    218219     * Looks for a certain entry inside a zip file and returns the entry path.
     
    292293     * Clear the cache for the given resource.
    293294     * This forces a fresh download.
    294      * @param name the URL 
     295     * @param name the URL
    295296     */
    296297    public static void cleanup(String name) {
     
    341342    private File checkLocal(URL url) throws IOException {
    342343        String prefKey = getPrefKey(url, destDir);
     344        String urlStr = url.toExternalForm();
    343345        long age = 0L;
    344346        long lMaxAge = maxAge;
     
    346348        File localFile = null;
    347349        List<String> localPathEntry = new ArrayList<>(Main.pref.getCollection(prefKey));
     350        boolean offline = false;
     351        try {
     352            checkOfflineAccess(urlStr);
     353        } catch (OfflineAccessException e) {
     354            offline = true;
     355        }
    348356        if (localPathEntry.size() == 2) {
    349357            localFile = new File(localPathEntry.get(1));
    350             if(!localFile.exists())
     358            if (!localFile.exists()) {
    351359                localFile = null;
    352             else {
     360            } else {
    353361                if ( maxAge == DEFAULT_MAXTIME
    354362                        || maxAge <= 0 // arbitrary value <= 0 is deprecated
     
    357365                }
    358366                age = System.currentTimeMillis() - Long.parseLong(localPathEntry.get(0));
    359                 if (age < lMaxAge*1000) {
     367                if (offline || age < lMaxAge*1000) {
    360368                    return localFile;
    361369                }
     
    373381            destDirFile.mkdirs();
    374382        }
    375        
    376         String a = url.toString().replaceAll("[^A-Za-z0-9_.-]", "_");
     383
     384        // No local file + offline => nothing to do
     385        if (offline) {
     386            return null;
     387        }
     388
     389        String a = urlStr.replaceAll("[^A-Za-z0-9_.-]", "_");
    377390        String localPath = "mirror_" + a;
    378391        destDirFile = new File(destDir, localPath + ".tmp");
     
    380393            HttpURLConnection con = connectFollowingRedirect(url, httpAccept, ifModifiedSince);
    381394            if (ifModifiedSince != null && con.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
    382                 Main.debug("304 Not Modified ("+url+")");
    383                 if (localFile == null) throw new AssertionError();
    384                 Main.pref.putCollection(prefKey,
     395                if (Main.isDebugEnabled()) {
     396                    Main.debug("304 Not Modified ("+urlStr+")");
     397                }
     398                if (localFile == null)
     399                    throw new AssertionError();
     400                Main.pref.putCollection(prefKey,
    385401                        Arrays.asList(Long.toString(System.currentTimeMillis()), localPathEntry.get(1)));
    386402                return localFile;
    387             } 
     403            }
    388404            try (
    389405                InputStream bis = new BufferedInputStream(con.getInputStream());
     
    398414            }
    399415            localFile = new File(destDir, localPath);
    400             if(Main.platform.rename(destDirFile, localFile)) {
    401                 Main.pref.putCollection(prefKey, 
     416            if (Main.platform.rename(destDirFile, localFile)) {
     417                Main.pref.putCollection(prefKey,
    402418                        Arrays.asList(Long.toString(System.currentTimeMillis()), localFile.toString()));
    403419            } else {
     
    407423        } catch (IOException e) {
    408424            if (age >= lMaxAge*1000 && age < lMaxAge*1000*2) {
    409                 Main.warn(tr("Failed to load {0}, use cached file and retry next time: {1}", url, e));
     425                Main.warn(tr("Failed to load {0}, use cached file and retry next time: {1}", urlStr, e));
    410426                return localFile;
    411427            } else {
     
    415431
    416432        return localFile;
     433    }
     434
     435    private static void checkOfflineAccess(String urlString) {
     436        OnlineResource.JOSM_WEBSITE.checkOfflineAccess(urlString, Main.getJOSMWebsite());
     437        OnlineResource.OSM_API.checkOfflineAccess(urlString, Main.pref.get("osm-server.url", OsmApi.DEFAULT_API_URL));
    417438    }
    418439
     
    424445     * is going from a http to a https URL, see <a href="https://bugs.openjdk.java.net/browse/JDK-4620571">bug report</a>.
    425446     * <p>
    426      * This can causes problems when downloading from certain GitHub URLs.
     447     * This can cause problems when downloading from certain GitHub URLs.
    427448     *
    428449     * @param downloadUrl The resource URL to download
     
    432453     * @throws MalformedURLException If a redirected URL is wrong
    433454     * @throws IOException If any I/O operation goes wrong
     455     * @throws OfflineAccessException if resource is accessed in offline mode, in any protocol
    434456     * @since 6867
    435457     */
    436458    public static HttpURLConnection connectFollowingRedirect(URL downloadUrl, String httpAccept, Long ifModifiedSince) throws MalformedURLException, IOException {
     459        CheckParameterUtil.ensureParameterNotNull(downloadUrl, "downloadUrl");
     460        String downloadString = downloadUrl.toExternalForm();
     461
     462        checkOfflineAccess(downloadString);
     463
    437464        HttpURLConnection con = null;
    438465        int numRedirects = 0;
    439466        while(true) {
    440467            con = Utils.openHttpConnection(downloadUrl);
     468            if (con == null) {
     469                throw new IOException("Cannot open http connection to "+downloadString);
     470            }
    441471            if (ifModifiedSince != null) {
    442472                con.setIfModifiedSince(ifModifiedSince);
     
    445475            con.setConnectTimeout(Main.pref.getInteger("socket.timeout.connect",15)*1000);
    446476            con.setReadTimeout(Main.pref.getInteger("socket.timeout.read",30)*1000);
    447             Main.debug("GET "+downloadUrl);
     477            if (Main.isDebugEnabled()) {
     478                Main.debug("GET "+downloadString);
     479            }
    448480            if (httpAccept != null) {
    449                 Main.debug("Accept: "+httpAccept);
     481                if (Main.isTraceEnabled()) {
     482                    Main.trace("Accept: "+httpAccept);
     483                }
    450484                con.setRequestProperty("Accept", httpAccept);
    451485            }
     
    466500            case HttpURLConnection.HTTP_SEE_OTHER:
    467501                String redirectLocation = con.getHeaderField("Location");
    468                 if (downloadUrl == null) {
    469                     /* I18n: argument is HTTP response code */ String msg = tr("Unexpected response from HTTP server. Got {0} response without ''Location'' header. Can''t redirect. Aborting.", con.getResponseCode());
     502                if (redirectLocation == null) {
     503                    /* I18n: argument is HTTP response code */
     504                    String msg = tr("Unexpected response from HTTP server. Got {0} response without ''Location'' header."+
     505                            " Can''t redirect. Aborting.", con.getResponseCode());
    470506                    throw new IOException(msg);
    471507                }
    472508                downloadUrl = new URL(redirectLocation);
     509                downloadString = downloadUrl.toExternalForm();
    473510                // keep track of redirect attempts to break a redirect loops if it happens
    474511                // to occur for whatever reason
     
    478515                    throw new IOException(msg);
    479516                }
    480                 Main.info(tr("Download redirected to ''{0}''", downloadUrl));
     517                Main.info(tr("Download redirected to ''{0}''", downloadString));
    481518                break;
    482519            default:
    483                 String msg = tr("Failed to read from ''{0}''. Server responded with status code {1}.", downloadUrl, con.getResponseCode());
     520                String msg = tr("Failed to read from ''{0}''. Server responded with status code {1}.", downloadString, con.getResponseCode());
    484521                throw new IOException(msg);
    485522            }
    486523        }
    487524    }
    488 
    489525}
  • trunk/src/org/openstreetmap/josm/io/MessageNotifier.java

    r6897 r7434  
    4040        // Hide default constructor for utils classes
    4141    }
    42    
     42
    4343    /** Property defining if this task is enabled or not */
    4444    public static final BooleanProperty PROP_NOTIFIER_ENABLED = new BooleanProperty("message.notifier.enabled", true);
    4545    /** Property defining the update interval in minutes */
    4646    public static final IntegerProperty PROP_INTERVAL = new IntegerProperty("message.notifier.interval", 5);
    47    
     47
    4848    private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
    49    
     49
    5050    private static final Runnable WORKER = new Worker();
    51    
     51
    5252    private static ScheduledFuture<?> task = null;
    53        
     53
    5454    private static class Worker implements Runnable {
    5555
     
    8282        }
    8383    }
    84    
     84
    8585    /**
    8686     * Starts the message notifier task if not already started and if user is fully identified
     
    8888    public static void start() {
    8989        int interval = PROP_INTERVAL.get();
    90         if (!isRunning() && interval > 0 && isUserEnoughIdentified()) {
     90        if (Main.isOffline(OnlineResource.OSM_API)) {
     91            Main.info(tr("{0} not available (offline mode)", tr("Message notifier")));
     92        } else if (!isRunning() && interval > 0 && isUserEnoughIdentified()) {
    9193            task = EXECUTOR.scheduleAtFixedRate(WORKER, 0, interval * 60, TimeUnit.SECONDS);
    9294            Main.info("Message notifier active (checks every "+interval+" minute"+(interval>1?"s":"")+")");
     
    104106        }
    105107    }
    106    
     108
    107109    /**
    108110     * Determines if the message notifier is currently running
     
    112114        return task != null;
    113115    }
    114    
     116
    115117    /**
    116118     * Determines if user set enough information in JOSM preferences to make the request to OSM API without
  • trunk/src/org/openstreetmap/josm/io/OsmApi.java

    r7082 r7434  
    9898    }
    9999
     100    private static String getServerUrlFromPref() {
     101        return Main.pref.get("osm-server.url", DEFAULT_API_URL);
     102    }
     103
    100104    /**
    101105     * Replies the {@link OsmApi} for the URL given by the preference <code>osm-server.url</code>
     
    104108     */
    105109    public static OsmApi getOsmApi() {
    106         String serverUrl = Main.pref.get("osm-server.url", DEFAULT_API_URL);
    107         return getOsmApi(serverUrl);
     110        return getOsmApi(getServerUrlFromPref());
    108111    }
    109112
     
    180183    private class CapabilitiesCache extends CacheCustomContent<OsmTransferException> {
    181184
     185        private static final String CAPABILITIES = "capabilities";
     186
    182187        ProgressMonitor monitor;
    183188        boolean fastFail;
    184189
    185190        public CapabilitiesCache(ProgressMonitor monitor, boolean fastFail) {
    186             super("capabilities" + getBaseUrl().hashCode(), CacheCustomContent.INTERVAL_WEEKLY);
     191            super(CAPABILITIES + getBaseUrl().hashCode(), CacheCustomContent.INTERVAL_WEEKLY);
    187192            this.monitor = monitor;
    188193            this.fastFail = fastFail;
     
    190195
    191196        @Override
     197        protected void checkOfflineAccess() {
     198            OnlineResource.OSM_API.checkOfflineAccess(getBaseUrl(getServerUrlFromPref(), "0.6")+CAPABILITIES, getServerUrlFromPref());
     199        }
     200
     201        @Override
    192202        protected byte[] updateData() throws OsmTransferException {
    193             return sendRequest("GET", "capabilities", null, monitor, false, fastFail).getBytes(StandardCharsets.UTF_8);
     203            return sendRequest("GET", CAPABILITIES, null, monitor, false, fastFail).getBytes(StandardCharsets.UTF_8);
    194204        }
    195205    }
     
    217227        if (initialized)
    218228            return;
     229        if (Main.isOffline(OnlineResource.OSM_API)) {
     230            // At this point this is an error because all automatic or UI actions requiring OSM API should have been disabled earlier
     231            throw new OfflineAccessException(tr("{0} not available (offline mode)", OnlineResource.OSM_API.getLocName()));
     232        }
    219233        cancel = false;
    220234        try {
     
    324338    }
    325339
    326     /**
    327      * Returns the base URL for API requests, including the negotiated version number.
    328      * @return base URL string
    329      */
    330     public String getBaseUrl() {
     340    private static String getBaseUrl(String serverUrl, String version) {
    331341        StringBuilder rv = new StringBuilder(serverUrl);
    332342        if (version != null) {
     
    339349        int p; while ((p = rv.indexOf("//", rv.indexOf("://")+2)) > -1) { rv.delete(p, p + 1); }
    340350        return rv.toString();
     351    }
     352
     353    /**
     354     * Returns the base URL for API requests, including the negotiated version number.
     355     * @return base URL string
     356     */
     357    public String getBaseUrl() {
     358        return getBaseUrl(serverUrl, version);
    341359    }
    342360
  • trunk/src/org/openstreetmap/josm/io/OsmServerReader.java

    r7267 r7434  
    118118    protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor, String reason, boolean uncompressAccordingToContentDisposition) throws OsmTransferException {
    119119        try {
     120            OnlineResource.JOSM_WEBSITE.checkOfflineAccess(urlStr, Main.getJOSMWebsite());
     121            OnlineResource.OSM_API.checkOfflineAccess(urlStr, Main.pref.get("osm-server.url", OsmApi.DEFAULT_API_URL));
     122
    120123            URL url = null;
    121124            try {
  • trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java

    r7424 r7434  
    6363import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
    6464import org.openstreetmap.josm.gui.widgets.JosmTextArea;
     65import org.openstreetmap.josm.io.OfflineAccessException;
     66import org.openstreetmap.josm.io.OnlineResource;
    6567import org.openstreetmap.josm.tools.GBC;
    6668import org.openstreetmap.josm.tools.I18n;
     
    303305     */
    304306    public static boolean checkAndConfirmPluginUpdate(Component parent) {
     307        if (!checkOfflineAccess()) {
     308            Main.info(tr("{0} not available (offline mode)", tr("Plugin update")));
     309            return false;
     310        }
    305311        String message = null;
    306312        String togglePreferenceKey = null;
     
    403409        }
    404410        return ret == 0;
     411    }
     412
     413    private static boolean checkOfflineAccess() {
     414        if (Main.isOffline(OnlineResource.ALL)) {
     415            return false;
     416        }
     417        if (Main.isOffline(OnlineResource.JOSM_WEBSITE)) {
     418            for (String updateSite : Main.pref.getPluginSites()) {
     419                try {
     420                    OnlineResource.JOSM_WEBSITE.checkOfflineAccess(updateSite, Main.getJOSMWebsite());
     421                } catch (OfflineAccessException e) {
     422                    if (Main.isTraceEnabled()) {
     423                        Main.trace(e.getMessage());
     424                    }
     425                    return false;
     426                }
     427            }
     428        }
     429        return true;
    405430    }
    406431
  • trunk/src/org/openstreetmap/josm/plugins/ReadRemotePluginInformationTask.java

    r7082 r7434  
    6060    protected enum CacheType {PLUGIN_LIST, ICON_LIST}
    6161
    62     protected final void init(Collection<String> sites, boolean displayErrMsg){
     62    protected final void init(Collection<String> sites, boolean displayErrMsg) {
    6363        this.sites = sites;
    6464        if (sites == null) {
     
    6868        this.displayErrMsg = displayErrMsg;
    6969    }
    70     /**
    71      * Creates the task
     70
     71    /**
     72     * Constructs a new {@code ReadRemotePluginInformationTask}.
    7273     *
    7374     * @param sites the collection of download sites. Defaults to the empty collection if null.
     
    7980
    8081    /**
    81      * Creates the task
     82     * Constructs a new {@code ReadRemotePluginInformationTask}.
    8283     *
    8384     * @param monitor the progress monitor. Defaults to {@link NullProgressMonitor#INSTANCE} if null
     
    104105
    105106    /**
    106      * Creates the file name for the cached plugin list and the icon cache
    107      * file.
     107     * Creates the file name for the cached plugin list and the icon cache file.
    108108     *
    109109     * @param site the name of the site
     
    403403            siteCacheFiles.remove(createSiteCacheFile(pluginDir, site, CacheType.PLUGIN_LIST));
    404404            siteCacheFiles.remove(createSiteCacheFile(pluginDir, site, CacheType.ICON_LIST));
    405             if(list != null)
    406             {
     405            if (list != null) {
    407406                getProgressMonitor().worked(1);
    408407                cachePluginList(site, list);
     
    416415            downloadPluginIcons(site+"-icons.zip", createSiteCacheFile(pluginDir, site, CacheType.ICON_LIST), getProgressMonitor().createSubTaskMonitor(0, false));
    417416        }
    418         for (File file: siteCacheFiles) /* remove old stuff or whole update process is broken */
    419         {
     417        // remove old stuff or whole update process is broken
     418        for (File file: siteCacheFiles) {
    420419            file.delete();
    421420        }
  • trunk/src/org/openstreetmap/josm/tools/ExceptionUtil.java

    r7299 r7434  
    2828import org.openstreetmap.josm.io.IllegalDataException;
    2929import org.openstreetmap.josm.io.MissingOAuthAccessTokenException;
     30import org.openstreetmap.josm.io.OfflineAccessException;
    3031import org.openstreetmap.josm.io.OsmApi;
    3132import org.openstreetmap.josm.io.OsmApiException;
     
    496497
    497498    /**
     499     * Explains a {@link OfflineAccessException} which has caused an {@link OsmTransferException}.
     500     * This is most likely happening when JOSM tries to access OSM API or JOSM website while in offline mode.
     501     *
     502     * @param e the exception
     503     * @return The HTML formatted error message to display
     504     * @since 7434
     505     */
     506    public static String explainOfflineAccessException(OsmTransferException e) {
     507        OfflineAccessException oae = getNestedException(e, OfflineAccessException.class);
     508        Main.error(e);
     509        return tr("<html>Failed to download data.<br>"
     510                + "<br>Details: {0}</html>", oae.getMessage());
     511    }
     512
     513    /**
    498514     * Explains a {@link OsmApiException} which was thrown because of an internal server
    499515     * error in the OSM API server..
  • trunk/src/org/openstreetmap/josm/tools/WikiReader.java

    r7401 r7434  
    3030     */
    3131    public WikiReader() {
    32         this.baseurl = Main.pref.get("help.baseurl", Main.getJOSMWebsite());
     32        this(Main.pref.get("help.baseurl", Main.getJOSMWebsite()));
     33    }
     34
     35    /**
     36     * Returns the base URL of wiki.
     37     * @return the base URL of wiki
     38     * @since 7434
     39     */
     40    public final String getBaseUrlWiki() {
     41        return baseurl + "/wiki/";
    3342    }
    3443
     
    4655        try (BufferedReader in = Utils.openURLReader(u)) {
    4756            boolean txt = url.endsWith("?format=txt");
    48             if (url.startsWith(baseurl) && !txt)
     57            if (url.startsWith(getBaseUrlWiki()) && !txt)
    4958                return readFromTrac(in, u);
    5059            return readNormal(in, !txt);
     
    6473        languageCode = LanguageInfo.getWikiLanguagePrefix(LocaleType.DEFAULTNOTENGLISH);
    6574        if(languageCode != null) {
    66             res = readLang(new URL(baseurl + "/wiki/" + languageCode + text));
     75            res = readLang(new URL(getBaseUrlWiki() + languageCode + text));
    6776        }
    6877
     
    7079            languageCode = LanguageInfo.getWikiLanguagePrefix(LocaleType.BASELANGUAGE);
    7180            if(languageCode != null) {
    72                 res = readLang(new URL(baseurl + "/wiki/" + languageCode + text));
     81                res = readLang(new URL(getBaseUrlWiki() + languageCode + text));
    7382            }
    7483        }
     
    7786            languageCode = LanguageInfo.getWikiLanguagePrefix(LocaleType.ENGLISH);
    7887            if(languageCode != null) {
    79                 res = readLang(new URL(baseurl + "/wiki/" + languageCode + text));
     88                res = readLang(new URL(getBaseUrlWiki() + languageCode + text));
    8089            }
    8190        }
Note: See TracChangeset for help on using the changeset viewer.