You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by ne...@apache.org on 2022/04/13 12:49:24 UTC
[netbeans-tools] branch master updated: Initial image creation for macOS pkg installer.
This is an automated email from the ASF dual-hosted git repository.
neilcsmith pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans-tools.git
The following commit(s) were added to refs/heads/master by this push:
new d6db73c Initial image creation for macOS pkg installer.
new 042c765 Merge pull request #49 from neilcsmith-net/nbpackage-macos
d6db73c is described below
commit d6db73c55bc9ba40efa54d093cb701a5e1a63306
Author: Neil C Smith <ne...@apache.org>
AuthorDate: Fri Mar 4 18:27:17 2022 +0000
Initial image creation for macOS pkg installer.
---
.../netbeans/nbpackage/AbstractPackagerTask.java | 8 +-
.../org/apache/netbeans/nbpackage/NBPackage.java | 3 +-
.../netbeans/nbpackage/macos/AppBundleTask.java | 197 +++++++++++++++++++++
.../netbeans/nbpackage/macos/PkgPackager.java | 76 ++++++++
.../apache/netbeans/nbpackage/macos/PkgTask.java | 48 +++++
.../apache/netbeans/nbpackage/apache-netbeans.icns | Bin 0 -> 168443 bytes
.../netbeans/nbpackage/macos/Info.plist.template | 37 ++++
.../netbeans/nbpackage/macos/Messages.properties | 20 +++
.../nbpackage/macos/Package.swift.template | 35 ++++
.../netbeans/nbpackage/macos/main.swift.template | 53 ++++++
10 files changed, 472 insertions(+), 5 deletions(-)
diff --git a/nbpackage/src/main/java/org/apache/netbeans/nbpackage/AbstractPackagerTask.java b/nbpackage/src/main/java/org/apache/netbeans/nbpackage/AbstractPackagerTask.java
index d77b04c..6bea23c 100644
--- a/nbpackage/src/main/java/org/apache/netbeans/nbpackage/AbstractPackagerTask.java
+++ b/nbpackage/src/main/java/org/apache/netbeans/nbpackage/AbstractPackagerTask.java
@@ -156,7 +156,7 @@ public abstract class AbstractPackagerTask implements Packager.Task {
private void extractAppFromArchive(Path input, Path destDir) throws IOException {
var tmp = Files.createTempDirectory("nbpackageImageExtract");
FileUtils.extractArchive(input, tmp);
- var images = FileUtils.findDirs(tmp, 2, "bin/*", "etc/*.conf");
+ var images = FileUtils.findDirs(tmp, 5, "bin/*", "etc/*.conf");
if (images.size() != 1) {
throw new IOException(input.toString());
}
@@ -165,7 +165,7 @@ public abstract class AbstractPackagerTask implements Packager.Task {
}
private void copyAppFromDirectory(Path input, Path destDir) throws IOException {
- var images = FileUtils.findDirs(input, 2, "bin/*", "etc/*.conf");
+ var images = FileUtils.findDirs(input, 5, "bin/*", "etc/*.conf");
if (images.size() != 1) {
throw new IOException(input.toString());
}
@@ -180,7 +180,7 @@ public abstract class AbstractPackagerTask implements Packager.Task {
private void extractRuntimeFromArchive(Path runtime, Path destDir) throws IOException {
var tmp = Files.createTempDirectory("nbpackageRuntimeExtract");
FileUtils.extractArchive(runtime, tmp);
- var runtimes = FileUtils.findDirs(tmp, 2, "bin/java*");
+ var runtimes = FileUtils.findDirs(tmp, 5, "bin/java*");
if (runtimes.size() != 1) {
throw new IOException(runtime.toString());
}
@@ -189,7 +189,7 @@ public abstract class AbstractPackagerTask implements Packager.Task {
}
private void copyRuntimeFromDirectory(Path runtime, Path destDir) throws IOException {
- var runtimes = FileUtils.findDirs(runtime, 2, "bin/java*");
+ var runtimes = FileUtils.findDirs(runtime, 5, "bin/java*");
if (runtimes.size() != 1) {
throw new IOException(runtime.toString());
}
diff --git a/nbpackage/src/main/java/org/apache/netbeans/nbpackage/NBPackage.java b/nbpackage/src/main/java/org/apache/netbeans/nbpackage/NBPackage.java
index 1ae29fa..06ea784 100644
--- a/nbpackage/src/main/java/org/apache/netbeans/nbpackage/NBPackage.java
+++ b/nbpackage/src/main/java/org/apache/netbeans/nbpackage/NBPackage.java
@@ -25,11 +25,11 @@ import java.nio.file.StandardOpenOption;
import java.text.MessageFormat;
import java.util.List;
import java.util.ResourceBundle;
-import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.netbeans.nbpackage.appimage.AppImagePackager;
import org.apache.netbeans.nbpackage.deb.DebPackager;
import org.apache.netbeans.nbpackage.innosetup.InnoSetupPackager;
+import org.apache.netbeans.nbpackage.macos.PkgPackager;
import org.apache.netbeans.nbpackage.zip.ZipPackager;
/**
@@ -70,6 +70,7 @@ public final class NBPackage {
new AppImagePackager(),
new DebPackager(),
new InnoSetupPackager(),
+ new PkgPackager(),
new ZipPackager()
);
diff --git a/nbpackage/src/main/java/org/apache/netbeans/nbpackage/macos/AppBundleTask.java b/nbpackage/src/main/java/org/apache/netbeans/nbpackage/macos/AppBundleTask.java
new file mode 100644
index 0000000..77d0924
--- /dev/null
+++ b/nbpackage/src/main/java/org/apache/netbeans/nbpackage/macos/AppBundleTask.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.netbeans.nbpackage.macos;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.apache.netbeans.nbpackage.AbstractPackagerTask;
+import org.apache.netbeans.nbpackage.ExecutionContext;
+import org.apache.netbeans.nbpackage.NBPackage;
+import org.apache.netbeans.nbpackage.StringUtils;
+
+import static org.apache.netbeans.nbpackage.macos.PkgPackager.*;
+
+/**
+ *
+ */
+class AppBundleTask extends AbstractPackagerTask {
+
+ private String bundleName;
+
+ AppBundleTask(ExecutionContext context) {
+ super(context);
+ }
+
+ @Override
+ public void validateCreatePackage() throws Exception {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Path createImage(Path input) throws Exception {
+ Path image = super.createImage(input);
+ Path bundle = image.resolve(getBundleName() + ".app");
+ Path contents = bundle.resolve("Contents");
+ Path resources = contents.resolve("Resources");
+
+ String execName = findLauncher(
+ resources
+ .resolve("APPDIR")
+ .resolve("bin"))
+ .getFileName().toString();
+ Files.move(resources.resolve("APPDIR"), resources.resolve(execName));
+
+ Files.createDirectory(contents.resolve("MacOS"));
+ setupIcons(resources, execName);
+ setupInfo(contents, execName);
+ setupLauncherSource(image);
+
+ return image;
+
+ }
+
+ @Override
+ public Path createPackage(Path image) throws Exception {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected String imageName(Path input) throws Exception {
+ return super.imageName(input) + "-macOS-app";
+ }
+
+ @Override
+ protected Path applicationDirectory(Path image) throws Exception {
+ return image.resolve(getBundleName() + ".app")
+ .resolve("Contents")
+ .resolve("Resources")
+ .resolve("APPDIR");
+ }
+
+ @Override
+ protected Path runtimeDirectory(Path image, Path application) throws Exception {
+ return image.resolve(getBundleName() + ".app")
+ .resolve("Contents")
+ .resolve("Home");
+ }
+
+ String getBundleName() {
+ if (bundleName == null) {
+ var name = sanitize(context().getValue(NBPackage.PACKAGE_NAME).orElseThrow());
+ if (name.length() > 15) {
+ name = name.substring(0, 16);
+ }
+ bundleName = name;
+ }
+ return bundleName;
+ }
+
+ private String sanitize(String name) {
+ return name.replaceAll("[\\\\/:*?\"<>|]", "_");
+ }
+
+ private String sanitizeBundleID(String name) {
+ return name.replaceAll("[^a-zA-Z0-9-\\.]", "-");
+ }
+
+ private Path findLauncher(Path binDir) throws IOException {
+ try ( var files = Files.list(binDir)) {
+ return files.filter(f -> !f.getFileName().toString().endsWith(".exe"))
+ .findFirst().orElseThrow(IOException::new);
+ }
+ }
+
+ private void setupIcons(Path resources, String execName) throws IOException {
+ Path icnsFile = context().getValue(MACOS_ICON).orElse(null);
+ Path dstFile = resources.resolve(execName + ".icns");
+ if (icnsFile != null) {
+ Files.copy(icnsFile, dstFile);
+ } else {
+ Files.copy(getClass().getResourceAsStream(
+ "/org/apache/netbeans/nbpackage/apache-netbeans.icns"), dstFile);
+ }
+ }
+
+ private void setupInfo(Path contents, String execName) throws IOException {
+ Path templateFile = context().getValue(MACOS_INFO_TEMPLATE).orElse(null);
+ String template;
+ try ( var reader = templateFile != null
+ ? Files.newBufferedReader(templateFile)
+ : new BufferedReader(
+ new InputStreamReader(
+ getClass().getResourceAsStream("Info.plist.template"),
+ StandardCharsets.UTF_8))) {
+ template = reader.lines().collect(Collectors.joining("\n", "", "\n"));
+ }
+
+ var tokenMap = Map.of(
+ "BUNDLE_NAME", getBundleName(),
+ "BUNDLE_DISPLAY", context().getValue(NBPackage.PACKAGE_NAME).orElseThrow(),
+ "BUNDLE_VERSION", context().getValue(NBPackage.PACKAGE_VERSION).orElseThrow(),
+ "BUNDLE_EXEC", execName,
+ "BUNDLE_ID", context().getValue(MACOS_BUNDLE_ID)
+ .orElse(sanitizeBundleID(getBundleName())),
+ "BUNDLE_ICON", execName + ".icns"
+ );
+
+ String info = StringUtils.replaceTokens(template, tokenMap);
+
+ Files.writeString(contents.resolve("Info.plist"), info,
+ StandardOpenOption.CREATE_NEW);
+
+ }
+
+ private void setupLauncherSource(Path image) throws IOException {
+ Path launcherProject = image.resolve("macos-launcher-src");
+ Files.createDirectories(launcherProject);
+ Path sourceDir = launcherProject.resolve("Sources").resolve("AppLauncher");
+ Files.createDirectories(sourceDir);
+
+ String packageSwift;
+ try ( var reader = new BufferedReader(
+ new InputStreamReader(
+ getClass().getResourceAsStream("Package.swift.template"),
+ StandardCharsets.UTF_8
+ ))) {
+ packageSwift = reader.lines().collect(Collectors.joining("\n", "", "\n"));
+ }
+
+ String mainSwift;
+ try ( var reader = new BufferedReader(
+ new InputStreamReader(
+ getClass().getResourceAsStream("main.swift.template"),
+ StandardCharsets.UTF_8
+ ))) {
+ mainSwift = reader.lines().collect(Collectors.joining("\n", "", "\n"));
+ }
+
+ Files.writeString(launcherProject.resolve("Package.swift"),
+ packageSwift, StandardOpenOption.CREATE_NEW);
+ Files.writeString(sourceDir.resolve("main.swift"),
+ mainSwift, StandardOpenOption.CREATE_NEW);
+ }
+
+}
diff --git a/nbpackage/src/main/java/org/apache/netbeans/nbpackage/macos/PkgPackager.java b/nbpackage/src/main/java/org/apache/netbeans/nbpackage/macos/PkgPackager.java
new file mode 100644
index 0000000..f8de2a8
--- /dev/null
+++ b/nbpackage/src/main/java/org/apache/netbeans/nbpackage/macos/PkgPackager.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.netbeans.nbpackage.macos;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.stream.Stream;
+import org.apache.netbeans.nbpackage.ExecutionContext;
+import org.apache.netbeans.nbpackage.Option;
+import org.apache.netbeans.nbpackage.Packager;
+
+/**
+ * Packager for macOS PKG installer.
+ */
+public class PkgPackager implements Packager {
+
+ static final ResourceBundle MESSAGES
+ = ResourceBundle.getBundle(PkgPackager.class.getPackageName() + ".Messages");
+
+ /**
+ * Value for CFBundleIdentifier.
+ */
+ public static final Option<String> MACOS_BUNDLE_ID
+ = Option.ofString("package.macos.bundleid", "",
+ MESSAGES.getString("option.bundle_id.description"));
+
+ /**
+ * Path to icon (*.icns) file.
+ */
+ public static final Option<Path> MACOS_ICON
+ = Option.ofPath("package.macos.icon", "",
+ MESSAGES.getString("option.icon.description"));
+
+ /**
+ * Optional Info.plist template.
+ */
+ public static final Option<Path> MACOS_INFO_TEMPLATE
+ = Option.ofPath("package.macos.info-template", "",
+ MESSAGES.getString("option.info_template.description"));
+
+ private static final List<Option<?>> PKG_OPTIONS = List.of(
+ MACOS_BUNDLE_ID, MACOS_ICON);
+
+ @Override
+ public Task createTask(ExecutionContext context) {
+ return new PkgTask(context);
+ }
+
+ @Override
+ public String name() {
+ return "macos-pkg";
+ }
+
+ @Override
+ public Stream<Option<?>> options() {
+ return PKG_OPTIONS.stream();
+ }
+
+}
diff --git a/nbpackage/src/main/java/org/apache/netbeans/nbpackage/macos/PkgTask.java b/nbpackage/src/main/java/org/apache/netbeans/nbpackage/macos/PkgTask.java
new file mode 100644
index 0000000..755fe37
--- /dev/null
+++ b/nbpackage/src/main/java/org/apache/netbeans/nbpackage/macos/PkgTask.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.netbeans.nbpackage.macos;
+
+import java.nio.file.Path;
+import org.apache.netbeans.nbpackage.ExecutionContext;
+
+/**
+ *
+ */
+class PkgTask extends AppBundleTask {
+
+ PkgTask(ExecutionContext context) {
+ super(context);
+ }
+
+ @Override
+ public Path createPackage(Path image) throws Exception {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void validateCreatePackage() throws Exception {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected String imageName(Path input) throws Exception {
+ return super.imageName(input) + "-pkg";
+ }
+
+}
diff --git a/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/apache-netbeans.icns b/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/apache-netbeans.icns
new file mode 100644
index 0000000..9f55491
Binary files /dev/null and b/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/apache-netbeans.icns differ
diff --git a/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/Info.plist.template b/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/Info.plist.template
new file mode 100644
index 0000000..5d69228
--- /dev/null
+++ b/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/Info.plist.template
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+
+ <key>CFBundleName</key>
+ <string>${BUNDLE_NAME}</string>
+
+ <key>CFBundleDisplayName</key>
+ <string>${BUNDLE_DISPLAY}</string>
+
+ <key>CFBundleVersion</key>
+ <string>${BUNDLE_VERSION}</string>
+
+ <key>CFBundleShortVersionString</key>
+ <string>${BUNDLE_VERSION}</string>
+
+ <key>CFBundleExecutable</key>
+ <string>${BUNDLE_EXEC}</string>
+
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+
+ <key>CFBundleIdentifier</key>
+ <string>${BUNDLE_ID}</string>
+
+ <key>CFBundleSignature</key>
+ <string>????</string>
+
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+
+ <key>CFBundleIconFile</key>
+ <string>${BUNDLE_ICON}</string>
+
+ </dict>
+</plist>
diff --git a/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/Messages.properties b/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/Messages.properties
new file mode 100644
index 0000000..b120e58
--- /dev/null
+++ b/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/Messages.properties
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+option.bundle_id.description=Value for CFBundleIdentifier.
+option.icon.description=Path to icon file (*.icns). Defaults to Apache NetBeans logo.
+option.info_template.description=Optional Info.plist template.
diff --git a/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/Package.swift.template b/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/Package.swift.template
new file mode 100644
index 0000000..0e9b7f1
--- /dev/null
+++ b/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/Package.swift.template
@@ -0,0 +1,35 @@
+// swift-tools-version:5.1
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import PackageDescription
+
+let package = Package(
+ name: "AppLauncher",
+ platforms: [
+ .macOS(.v10_13)
+ ],
+ dependencies: [],
+ targets: [
+ .target(
+ name: "AppLauncher",
+ dependencies: []),
+ ]
+)
diff --git a/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/main.swift.template b/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/main.swift.template
new file mode 100644
index 0000000..d080677
--- /dev/null
+++ b/nbpackage/src/main/resources/org/apache/netbeans/nbpackage/macos/main.swift.template
@@ -0,0 +1,53 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation
+
+let brandingToken = Bundle.main.object(forInfoDictionaryKey: "CFBundleExecutable") as? String
+let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String
+let launcherURL = Bundle.main.url(forResource: brandingToken, withExtension: "", subdirectory: brandingToken! + "/bin")
+
+var args = [String]()
+
+// check for JDK
+let fileManager = FileManager.default
+let jdkPath = Bundle.main.bundlePath + "/Contents/Home"
+
+if (fileManager.fileExists(atPath: jdkPath)) {
+ args.append("--jdkhome")
+ args.append(jdkPath)
+}
+
+// add user's command line arguments
+for argument in Array(CommandLine.arguments.dropFirst()) {
+ args.append(argument)
+}
+
+
+let launchNbexec = Process()
+var env = ProcessInfo.processInfo.environment
+env["APP_DOCK_NAME"] = appName
+launchNbexec.environment = env
+launchNbexec.arguments = args
+launchNbexec.executableURL = launcherURL
+try launchNbexec.run()
+
+// needed to keep Dock name based on CFBundleName from Info.plist
+// does not work if called from command line.
+launchNbexec.waitUntilExit()
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists