From 178d8dc0513061c57ac83784e39970e37a37ea5f Mon Sep 17 00:00:00 2001 From: Bradley Turek Date: Wed, 19 Dec 2018 12:28:48 -0700 Subject: [PATCH 1/9] Clarified how to use the two magical strings for cacheDir. A full explanation is coming in the Wiki. --- README.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d43568a..bebb449 100644 --- a/README.md +++ b/README.md @@ -116,16 +116,26 @@ Check out these prebuilt installers for a more complex demo application ## Specify cache directory -By default, the artifacts are downloaded to the current working directory. This is usually fine for native installers, but if you distribute -your application via just the launcher jar, you might want to specify where the downloaded artifacts land. See the -[cache dir documentation](https://github.com/edvin/fxlauncher/wiki/Optional-Cache-Directory) for more information. +By default, the artifacts are downloaded to the current working directory. This is usually fine for per-user native +installers, but if you distribute your application via a system-wide native installer, or just the launcher +jar, you might want to specify where the downloaded artifacts land. See the +[cache dir documentation] for more information. + +[cache dir documentation]: https://github.com/edvin/fxlauncher/wiki/Optional-Cache-Directory ## Installation location -It's worth noting that the two package alternatives for Windows, (EXE and MSI) have different install location defaults. -While EXE will default to %APPDATALOCAL%, the MSI installer will default to %ProgramFiles%. If you use the MSI installer you -might therefore need to specify the cache dir parameter as `cacheDir 'USERLIB/MyApp'` to make sure that the launcher has -write access to download the artifacts for your application. +It's worth noting that the two package alternatives for Windows, (EXE and MSI) have different default install locations. +While EXE will default to [`%AppDataLocal%`], the MSI installer will default to `%ProgramFiles%`. To write to +`%ProgramFiles%` one definitely does need admin privileges—that poses a problem for FXLauncher which, by default, +downloads updates to where it was installed. + +If you use the MSI installer you will therefore need to tell FXLauncher to cache artifacts somewhere it is allowed +to put them. For an OS-independent answer to this problem, look no further than the +[two magical strings][cache dir documentation], `USERLIB` and `ALLUSERS`. + + +[`%AppDataLocal%`]: https://www.howtogeek.com/318177/what-is-the-appdata-folder-in-windows/ Read more about Java Packager in the official documentation: From 372d667f09ce998409bf0094fdd22a68890bb769 Mon Sep 17 00:00:00 2001 From: Bradley Turek Date: Wed, 19 Dec 2018 14:40:54 -0700 Subject: [PATCH 2/9] Fixed one case of resolve, checking for a "/" and then adding on app.xml if necessary. --- src/main/java/fxlauncher/AbstractLauncher.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/fxlauncher/AbstractLauncher.java b/src/main/java/fxlauncher/AbstractLauncher.java index 172932a..2de2fa8 100644 --- a/src/main/java/fxlauncher/AbstractLauncher.java +++ b/src/main/java/fxlauncher/AbstractLauncher.java @@ -192,9 +192,15 @@ protected void syncManifest() throws Exception { } log.info(String.format("Syncing files from 'uri' parameter supplied: %s", uriStr)); + if (!uriStr.endsWith("/")) { + uriStr += "/"; + } URI uri = URI.create(uriStr); + // load manifest from --app param if supplied, else default file at supplied uri - URI app = appStr != null ? URI.create(appStr) : uri.resolve("app.xml"); + URI app = (appStr != null) + ? URI.create(appStr) + : URI.create(uriStr + "app.xml"); // We avoid using resolve here so as to not break UNC paths. See issue #143 manifest = FXManifest.load(app); // set supplied uri in manifest manifest.uri = uri; From cfa70b80f2fc565f5100dd93019fd78e37593f20 Mon Sep 17 00:00:00 2001 From: Bradley Turek Date: Wed, 19 Dec 2018 14:53:34 -0700 Subject: [PATCH 3/9] Fixed another case of resolve. Checking for "/" and acting accordingly. --- src/main/java/fxlauncher/FXManifest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/fxlauncher/FXManifest.java b/src/main/java/fxlauncher/FXManifest.java index c020a92..a983ed6 100644 --- a/src/main/java/fxlauncher/FXManifest.java +++ b/src/main/java/fxlauncher/FXManifest.java @@ -65,10 +65,13 @@ public String getFilename() { } public URI getFXAppURI() { - if (uri.getPath().endsWith("/")) - return uri.resolve("app.xml"); + String appXmlFile = "app.xml"; + if (!uri.getPath().endsWith("/")) { + appXmlFile = "/app.xml"; + } - return URI.create(uri.toString() + "/app.xml"); + // We avoid using resolve here so as to not break UNC paths. See issue #143 + return URI.create(uri.toString() + appXmlFile); } public Path getPath(Path cacheDir) { From 84d8a6e0d6342bc475ca9506f1a8c84249383f2e Mon Sep 17 00:00:00 2001 From: Bradley Turek Date: Wed, 19 Dec 2018 15:01:25 -0700 Subject: [PATCH 4/9] Fixed one more case of URI.resolve. Checking for "/" and acting accordingly. --- src/main/java/fxlauncher/AbstractLauncher.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/fxlauncher/AbstractLauncher.java b/src/main/java/fxlauncher/AbstractLauncher.java index 2de2fa8..b303e86 100644 --- a/src/main/java/fxlauncher/AbstractLauncher.java +++ b/src/main/java/fxlauncher/AbstractLauncher.java @@ -125,7 +125,15 @@ protected boolean syncFiles() throws Exception { Path target = cacheDir.resolve(lib.file).toAbsolutePath(); Files.createDirectories(target.getParent()); - URI uri = manifest.uri.resolve(lib.file); + URI uri; + if (!manifest.uri.getPath().endsWith("/")) { + // We avoid using resolve here so as to not break UNC paths. See issue #143 + uri = URI.create(manifest.uri.toString() + "/" + lib.file); + } else { + // We avoid using resolve here so as to not break UNC paths. See issue #143 + uri = URI.create(manifest.uri.toString() + lib.file); + } + try (InputStream input = openDownloadStream(uri); OutputStream output = Files.newOutputStream(target)) { From d64267832770cbf18b931d601d7f4b7d7348300d Mon Sep 17 00:00:00 2001 From: Bradley Turek Date: Wed, 19 Dec 2018 15:05:22 -0700 Subject: [PATCH 5/9] Clarified the comment referring to the issue to make it clearer which resolve method we mean. --- src/main/java/fxlauncher/AbstractLauncher.java | 6 +++--- src/main/java/fxlauncher/FXManifest.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/fxlauncher/AbstractLauncher.java b/src/main/java/fxlauncher/AbstractLauncher.java index b303e86..9dbf753 100644 --- a/src/main/java/fxlauncher/AbstractLauncher.java +++ b/src/main/java/fxlauncher/AbstractLauncher.java @@ -127,10 +127,10 @@ protected boolean syncFiles() throws Exception { URI uri; if (!manifest.uri.getPath().endsWith("/")) { - // We avoid using resolve here so as to not break UNC paths. See issue #143 + // We avoid using uri.resolve() here so as to not break UNC paths. See issue #143 uri = URI.create(manifest.uri.toString() + "/" + lib.file); } else { - // We avoid using resolve here so as to not break UNC paths. See issue #143 + // We avoid using uri.resolve() here so as to not break UNC paths. See issue #143 uri = URI.create(manifest.uri.toString() + lib.file); } @@ -208,7 +208,7 @@ protected void syncManifest() throws Exception { // load manifest from --app param if supplied, else default file at supplied uri URI app = (appStr != null) ? URI.create(appStr) - : URI.create(uriStr + "app.xml"); // We avoid using resolve here so as to not break UNC paths. See issue #143 + : URI.create(uriStr + "app.xml"); // We avoid using uri.resolve() here so as to not break UNC paths. See issue #143 manifest = FXManifest.load(app); // set supplied uri in manifest manifest.uri = uri; diff --git a/src/main/java/fxlauncher/FXManifest.java b/src/main/java/fxlauncher/FXManifest.java index a983ed6..cf9350e 100644 --- a/src/main/java/fxlauncher/FXManifest.java +++ b/src/main/java/fxlauncher/FXManifest.java @@ -70,7 +70,7 @@ public URI getFXAppURI() { appXmlFile = "/app.xml"; } - // We avoid using resolve here so as to not break UNC paths. See issue #143 + // We avoid using uri.resolve() here so as to not break UNC paths. See issue #143 return URI.create(uri.toString() + appXmlFile); } From 2283f398dd79376fb17550fe7fc84e9c34edf2ad Mon Sep 17 00:00:00 2001 From: Bradley Turek Date: Thu, 20 Dec 2018 09:27:58 -0700 Subject: [PATCH 6/9] Written much cleaner per edvin's comments. --- src/main/java/fxlauncher/AbstractLauncher.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/fxlauncher/AbstractLauncher.java b/src/main/java/fxlauncher/AbstractLauncher.java index 9dbf753..e160d22 100644 --- a/src/main/java/fxlauncher/AbstractLauncher.java +++ b/src/main/java/fxlauncher/AbstractLauncher.java @@ -126,13 +126,10 @@ protected boolean syncFiles() throws Exception { Files.createDirectories(target.getParent()); URI uri; - if (!manifest.uri.getPath().endsWith("/")) { - // We avoid using uri.resolve() here so as to not break UNC paths. See issue #143 - uri = URI.create(manifest.uri.toString() + "/" + lib.file); - } else { - // We avoid using uri.resolve() here so as to not break UNC paths. See issue #143 - uri = URI.create(manifest.uri.toString() + lib.file); - } + + // We avoid using uri.resolve() here so as to not break UNC paths. See issue #143 + String separator = manifest.uri.getPath().endsWith("/") ? "" : "/"; + uri = URI.create(manifest.uri.toString() + separator + lib.file); try (InputStream input = openDownloadStream(uri); OutputStream output = Files.newOutputStream(target)) { From 38b7b008eba33a83959a8934ecfbbf1f3b473c44 Mon Sep 17 00:00:00 2001 From: Bradley Turek Date: Thu, 20 Dec 2018 09:30:35 -0700 Subject: [PATCH 7/9] Checking if appStr has a slash per edvin's comments. --- src/main/java/fxlauncher/AbstractLauncher.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/fxlauncher/AbstractLauncher.java b/src/main/java/fxlauncher/AbstractLauncher.java index e160d22..6d097fe 100644 --- a/src/main/java/fxlauncher/AbstractLauncher.java +++ b/src/main/java/fxlauncher/AbstractLauncher.java @@ -189,6 +189,10 @@ protected void syncManifest() throws Exception { log.info(String.format("Loading manifest from 'app' parameter supplied: %s", appStr)); } + if (appStr != null && !appStr.endsWith("/")) { + appStr += "/"; + } + if (namedParams.containsKey("uri")) { // get --uri-param String uriStr = namedParams.get("uri"); From 390e702e40a0920598c5ba1f96d510a18184aa41 Mon Sep 17 00:00:00 2001 From: Bradley Turek Date: Thu, 20 Dec 2018 09:34:15 -0700 Subject: [PATCH 8/9] Now using the separator logic as was previously used. --- src/main/java/fxlauncher/FXManifest.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/fxlauncher/FXManifest.java b/src/main/java/fxlauncher/FXManifest.java index cf9350e..62df620 100644 --- a/src/main/java/fxlauncher/FXManifest.java +++ b/src/main/java/fxlauncher/FXManifest.java @@ -65,13 +65,11 @@ public String getFilename() { } public URI getFXAppURI() { - String appXmlFile = "app.xml"; - if (!uri.getPath().endsWith("/")) { - appXmlFile = "/app.xml"; - } + + String separator = uri.getPath().endsWith("/") ? "" : "/"; // We avoid using uri.resolve() here so as to not break UNC paths. See issue #143 - return URI.create(uri.toString() + appXmlFile); + return URI.create(uri.toString() + separator + "app.xml"); } public Path getPath(Path cacheDir) { From c1d0ae375613757ebbddf34bd26b58cccdbcfa40 Mon Sep 17 00:00:00 2001 From: Bradley Turek Date: Thu, 20 Dec 2018 12:26:01 -0700 Subject: [PATCH 9/9] Added a bit about the UNC paths to the README. --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bebb449..15ae172 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,13 @@ Notice: `WhatsNew` is not supported. ### File based deployment -The app uri can be a file:// based url instead of an web uri if your application is hosted on a common network location for your users. +The app uri can be a `file://` based url instead of a web uri if your application is hosted on a common network location for your users. + +#### UNC Paths +FXLauncher can deal with [UNC paths], if you ask it nicely. Instead of `\\server\share\myapp` use `file:////server/share/myapp`. +Yes, that's four forward slashes; two for the `file://` protocol and two for the UNC path. + +[UNC paths]: https://www.lifewire.com/unc-universal-naming-convention-818230 ### Native installers