Hi Michael,

I think it will be a problem to implement this for native launchers.
- If we extract native launchers inside installed app bundle it will invalidate 
signature and most likely will require privileged permissions to write inside 
app bundle.
- If we extract to some known and accessible location as you suggesting, then 
how our launchers will figure out which runtime to use? All other runtime files 
will be inside app bundle.
- If user deletes application, then how we will cleanup extracted files? Most 
likely it will require uninstall script in known location which user will need 
to run in order to cleanup extracted files.

Thanks,
Alexander

On May 18, 2022, at 6:44 PM, Michael Hall 
<mik3h...@gmail.com<mailto:mik3h...@gmail.com>> wrote:



On May 11, 2022, at 4:39 PM, Alexander Matveev 
<almat...@openjdk.java.net<mailto:almat...@openjdk.java.net>> wrote:

- It is not possible to support native JDK commands such as "java" inside Mac 
App Store bundles due to embedded info.plist. Workarounds suggested in 
JDK-8286122 does not seems to be visible.

I was just thinking about this. If you wanted a workaround to suggest to the 
user on the original issue. You could jar the native executables, extract them 
to a known accessible location, and then runtime them.

Having the commands jar’d would get them past the App Store check. Runtime on 
the client machine I doubt would object to the duplicate bundle id’s on 
absolute path execution but I haven’t double checked that. Also avoids issues 
with quarantine xattr’s.
I’ve done something like this a couple times for interfacing an app to other 
languages.

For example…

if (Files.exists(rscriptCmd)) {
isR = true;
System.out.println("InitialFinance: RScript available");
// Where is the finance data directory?
String data = prefs.get("data","N/A");

if (data.equals("N/A")) {
Application app = Application.getApplication();
Path documents = app.getFolder(DataTypes.DOCUMENTS);
dataLoc = Paths.get(documents.toString(),"finance");
}
else {
dataLoc = Paths.get(data);
}
System.out.println("InitialFinance: data location is " + dataLoc);
Path resourceJar = Paths.get(System.getProperty("app.path"),"resource.jar");
System.out.println("InitialFinance: Checking resources for updates");
extractArchive(resourceJar,dataLoc);
}
else {
System.out.println("InitialFinance: " + rscriptCmd + " for " + initialRscript + 
" does not exist");
isR = false;
}

// 
https://stackoverflow.com/questions/1529611/how-to-write-a-java-program-which-can-extract-a-jar-file-and-store-its-data-in-s
    public static void extractArchive(Path archiveFile, Path destPath) throws 
IOException {
        Files.createDirectories(destPath); // create dest path folder(s)
        try (ZipFile archive = new ZipFile(archiveFile.toFile())) {

         @SuppressWarnings("unchecked")
         Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) 
archive.entries();

            // copy or create new or updated
         while (entries.hasMoreElements()) {
         ZipEntry entry = entries.nextElement();

         if (!entry.getName().startsWith("finance/") || 
!(entry.getName().length() > 8)) {
         continue;
         }
         String fileName = entry.getName().substring(8);
         FileTime archiveTime = entry.getLastModifiedTime();

                Path entryDest = destPath.resolve(fileName);
                //if (Files.isDirectory(entryDest)) continue;
                //Files.createDirectories(entryDest);
         if (!Files.exists(entryDest)) {
         Files.copy(archive.getInputStream(entry), entryDest, 
StandardCopyOption.REPLACE_EXISTING);
         continue;
         }
                BasicFileAttributes destAttr =
                        Files.readAttributes(entryDest, 
BasicFileAttributes.class);

                if (archiveTime.compareTo(destAttr.creationTime()) > 0) {
                    Files.copy(archive.getInputStream(entry), entryDest, 
StandardCopyOption.REPLACE_EXISTING);
                }
            }
        }
        catch (IOException ioex) {
         throw ioex;
        }
    }

boolean debug = Boolean.getBoolean("R.debug");
rtexec(new String[] { RSCRIPT, script.toString() },debug);


Reply via email to