# HG changeset patch # User Jiri Vanek # Date 1407429580 -7200 # Node ID 6f45fbbf26a66d01dd92d010cc5e514ceed449b8 # Parent 247a09f2cd10718fb9a3dd47f12eb1bb70744429 Massively improved offline abilities. diff -r 247a09f2cd10 -r 6f45fbbf26a6 ChangeLog --- a/ChangeLog Fri Aug 01 11:25:44 2014 +0200 +++ b/ChangeLog Thu Aug 07 18:39:40 2014 +0200 @@ -1,3 +1,22 @@ +2014-08-05 Jiri Vanek + + Massively improved offline abilities. Added Xoffline switch to force work without inet connection. + * NEWS: updated + * netx/net/sourceforge/jnlp/JNLPFile.java: (openURL) is now using properly + cached file instead of direct online one. + * netx/net/sourceforge/jnlp/Launcher.java: launcher is now using JNLPRuntime + isOnline* set of methods + * netx/net/sourceforge/jnlp/cache/ResourceTracker.java: misleading + (getInputStream) method removed (initializeResource) check for connection + before downlaodin (unless Xforceoffline specified). If environment is offline + it do not attempt any url connections or writing to cache + * netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java: added flags of (offlineForced) + and (onlineDetected) with getters and setters. Added utility method (detectOnline) + to recognize whether environment is onliune by resovling inet addres of host + of not file url. + * netx/net/sourceforge/jnlp/util/XDesktopEntry.java: now writes real url into + desktop icon + 2014-08-01 Jiri Vanek * plugin/icedteanp/java/sun/applet/PluginAppletViewer.java: casts to diff -r 247a09f2cd10 -r 6f45fbbf26a6 NEWS --- a/NEWS Fri Aug 01 11:25:44 2014 +0200 +++ b/NEWS Thu Aug 07 18:39:40 2014 +0200 @@ -9,6 +9,7 @@ CVE-XXXX-YYYY: http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=XXXX-YYYY New in release 1.5.1 (YYYY-MM-DD): +* Massively improved offline abilities. * Improved to be able to run with any JDK * JDK 8 support added (URLPermission granted if applicable) * Added DE and PL localizations diff -r 247a09f2cd10 -r 6f45fbbf26a6 netx/net/sourceforge/jnlp/JNLPFile.java --- a/netx/net/sourceforge/jnlp/JNLPFile.java Fri Aug 01 11:25:44 2014 +0200 +++ b/netx/net/sourceforge/jnlp/JNLPFile.java Thu Aug 07 18:39:40 2014 +0200 @@ -16,6 +16,8 @@ package net.sourceforge.jnlp; +import java.io.File; +import java.io.FileInputStream; import static net.sourceforge.jnlp.runtime.Translator.R; import java.io.IOException; @@ -301,8 +303,8 @@ try { ResourceTracker tracker = new ResourceTracker(false); // no prefetch tracker.addResource(location, version, null, policy); - - return tracker.getInputStream(location); + File f = tracker.getCacheFile(location); + return new FileInputStream(f); } catch (Exception ex) { throw new IOException(ex.getMessage()); } diff -r 247a09f2cd10 -r 6f45fbbf26a6 netx/net/sourceforge/jnlp/Launcher.java --- a/netx/net/sourceforge/jnlp/Launcher.java Fri Aug 01 11:25:44 2014 +0200 +++ b/netx/net/sourceforge/jnlp/Launcher.java Thu Aug 07 18:39:40 2014 +0200 @@ -227,16 +227,10 @@ //First checks whether offline-allowed tag is specified inside the jnlp //file. if (!file.getInformation().isOfflineAllowed()) { - try { - //Checks the offline/online status of the system. - //If system is offline do not launch. - InetAddress.getByName(file.getSourceLocation().getHost()); - - } catch (UnknownHostException ue) { + //offline status should be already known from jnlp downloading + if (!JNLPRuntime.isOnlineDetected()) { OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "File cannot be launched because offline-allowed tag not specified and system currently offline."); return null; - } catch (Exception e) { - OutputController.getLogger().log(e); } } diff -r 247a09f2cd10 -r 6f45fbbf26a6 netx/net/sourceforge/jnlp/cache/ResourceTracker.java --- a/netx/net/sourceforge/jnlp/cache/ResourceTracker.java Fri Aug 01 11:25:44 2014 +0200 +++ b/netx/net/sourceforge/jnlp/cache/ResourceTracker.java Thu Aug 07 18:39:40 2014 +0200 @@ -25,9 +25,11 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; +import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; +import java.net.UnknownHostException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; @@ -404,33 +406,7 @@ } } - /** - * Returns an input stream that reads the contents of the - * resource. For non-cacheable resources, an InputStream that - * reads from the source location is returned. Otherwise the - * InputStream reads the cached resource. - *

- * This method will block while the resource is downloaded to - * the cache. - *

- * - * @throws IOException if there was an error opening the stream - * @throws IllegalResourceDescriptorException if the resource is not being tracked - */ - public InputStream getInputStream(URL location) throws IOException { - try { - Resource resource = getResource(location); - if (!resource.isSet(DOWNLOADED | ERROR)) - waitForResource(location, 0); - if (resource.localFile != null) - return new FileInputStream(resource.localFile); - - return resource.location.openStream(); - } catch (InterruptedException ex) { - throw new IOException("wait was interrupted"); - } - } /** * Wait for a group of resources to be downloaded and made @@ -776,6 +752,10 @@ * fields. */ private void initializeResource(Resource resource) { + //verify connection + if(!JNLPRuntime.isOfflineForced()){ + JNLPRuntime.detectOnline(resource.getLocation()/*or doenloadLocation*/); + } resource.fireDownloadEvent(); // fire CONNECTING CacheEntry entry = new CacheEntry(resource.location, resource.requestVersion); @@ -783,31 +763,41 @@ try { File localFile = CacheUtil.getCacheFile(resource.location, resource.downloadVersion); - - // connect - URL finalLocation = findBestUrl(resource); + long size = 0; + boolean current = true; + //this can be null, as it is always filled in online mode, and never read in offline mode + URLConnection connection = null; + if (localFile != null) { + size = localFile.length(); + } else if (!JNLPRuntime.isOnline()) { + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "You are trying to get resource " + resource.getLocation().toExternalForm() + " but you are in offline mode, and it is not in cache. Attempting to continue, but you may expect failure"); + } + if (JNLPRuntime.isOnline()) { + // connect + URL finalLocation = findBestUrl(resource); - if (finalLocation == null) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Attempted to download " + resource.location + ", but failed to connect!"); - throw new NullPointerException("finalLocation == null"); // Caught below - } - - resource.setDownloadLocation(finalLocation); - URLConnection connection = finalLocation.openConnection(); // this won't change so should be okay unsynchronized - connection.addRequestProperty("Accept-Encoding", "pack200-gzip, gzip"); + if (finalLocation == null) { + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Attempted to download " + resource.location + ", but failed to connect!"); + throw new NullPointerException("finalLocation == null"); // Caught below + } - int size = connection.getContentLength(); - boolean current = CacheUtil.isCurrent(resource.location, resource.requestVersion, connection) && resource.getUpdatePolicy() != UpdatePolicy.FORCE; - if (!current) { - if (entry.isCached()) { - entry.markForDelete(); - entry.store(); - // Old entry will still exist. (but removed at cleanup) - localFile = CacheUtil.makeNewCacheFile(resource.location, resource.downloadVersion); - CacheEntry newEntry = new CacheEntry(resource.location, resource.requestVersion); - newEntry.lock(); - entry.unlock(); - entry = newEntry; + resource.setDownloadLocation(finalLocation); + connection = finalLocation.openConnection(); // this won't change so should be okay unsynchronized + connection.addRequestProperty("Accept-Encoding", "pack200-gzip, gzip"); + + size = connection.getContentLength(); + current = CacheUtil.isCurrent(resource.location, resource.requestVersion, connection) && resource.getUpdatePolicy() != UpdatePolicy.FORCE; + if (!current) { + if (entry.isCached()) { + entry.markForDelete(); + entry.store(); + // Old entry will still exist. (but removed at cleanup) + localFile = CacheUtil.makeNewCacheFile(resource.location, resource.downloadVersion); + CacheEntry newEntry = new CacheEntry(resource.location, resource.requestVersion); + newEntry.lock(); + entry.unlock(); + entry = newEntry; + } } } @@ -823,7 +813,7 @@ } // update cache entry - if (!current) + if (!current && JNLPRuntime.isOnline()) entry.initialize(connection); entry.setLastUpdated(System.currentTimeMillis()); diff -r 247a09f2cd10 -r 6f45fbbf26a6 netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java --- a/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java Fri Aug 01 11:25:44 2014 +0200 +++ b/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java Thu Aug 07 18:39:40 2014 +0200 @@ -24,7 +24,10 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.Authenticator; +import java.net.InetAddress; import java.net.ProxySelector; +import java.net.URL; +import java.net.UnknownHostException; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.security.AllPermission; @@ -157,6 +160,12 @@ /** allows 301.302.303.307.308 redirects to be followed when downloading resources*/ private static boolean allowRedirect = false;; + + /** when this is true, ITW will not attempt any inet connections and will work only with what is in cache*/ + private static boolean offlineForced = false; + + private static Boolean onlineDetected = null; + /** * Header is not checked and so eg @@ -377,6 +386,54 @@ new ParserDelegator(); } + + + + + + + public static boolean isOfflineForced() { + return offlineForced; + } + + public static void setOnlineDetected(boolean online) { + onlineDetected = online; + OutputController.getLogger().log(OutputController.Level.MESSAGE_DEBUG, "Detected online set to: " + onlineDetected); + } + + public static boolean isOnlineDetected() { + if (onlineDetected == null) { + //"file" protocol do not do online check + //sugest online for this case + return true; + } + return onlineDetected; + } + + public static boolean isOnline() { + if (isOfflineForced()) { + return false; + } + return isOnlineDetected(); + } + + public static void detectOnline(URL location) { + if (onlineDetected != null) { + return; + } + try { + if (location.getProtocol().equals("file")) { + return; + } + //Checks the offline/online status of the system. + InetAddress.getByName(location.getHost()); + } catch (UnknownHostException ue) { + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "The host of " + location.toExternalForm() + " file should be located seems down, or you are simply offline."); + JNLPRuntime.setOnlineDetected(false); + return; + } + setOnlineDetected(true); + } /** * see Double-checked locking in Java diff -r 247a09f2cd10 -r 6f45fbbf26a6 netx/net/sourceforge/jnlp/util/XDesktopEntry.java --- a/netx/net/sourceforge/jnlp/util/XDesktopEntry.java Fri Aug 01 11:25:44 2014 +0200 +++ b/netx/net/sourceforge/jnlp/util/XDesktopEntry.java Thu Aug 07 18:39:40 2014 +0200 @@ -102,8 +102,8 @@ fileContents += "Vendor=" + sanitize(file.getInformation().getVendor()) + "\n"; } - //Shortcut executes the jnlp from cache and system preferred java.. - fileContents += "Exec=" + "javaws" + " \"" + cacheFile.getAbsolutePath() + "\"\n"; + //Shortcut executes the jnlp as it was with system preferred java. It should work fine offline + fileContents += "Exec=" + "javaws" + " \"" + file.getSourceLocation() + "\"\n"; return new StringReader(fileContents);