RFR: 8286122: [macos]: App bundle cannot upload to Mac App Store due to info.plist embedded in java exe

Alexander Matveev alexander.matveev at oracle.com
Thu May 19 22:38:19 UTC 2022


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 <mik3hall at gmail.com<mailto:mik3hall at gmail.com>> wrote:



On May 11, 2022, at 4:39 PM, Alexander Matveev <almatvee at openjdk.java.net<mailto:almatvee at 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);




More information about the core-libs-dev mailing list