Ignore:
Timestamp:
2014-08-20T03:07:15+02:00 (12 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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.