package fxlauncher; import javax.xml.bind.JAXB; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class CreateManifest { private static ArrayList<String> includeExtensions = new ArrayList<>(); static { includeExtensions.addAll(Arrays.asList("jar", "war")); } public static void main(String[] args) throws IOException, URISyntaxException { URI baseURI = URI.create(args[0]); String launchClass = args[1]; Path appPath = Paths.get(args[2]); String updateText = null; String updateLabelStyle = null; String progressBarStyle = null; String wrapperStyle = null; String cacheDir = null; Boolean acceptDowngrade = null; Boolean stopOnUpdateErrors = null; String parameters = null; String whatsNew = null; String preloadNativeLibraries = null; Boolean lingeringUpdateScreen = false; Boolean stopOnUpdateErrorsDeprecated = null; if (args.length > 3) { // Parse named parameters List<String> rawParams = new ArrayList<>(); rawParams.addAll(Arrays.asList(args).subList(3, args.length)); LauncherParams params = new LauncherParams(rawParams); Map<String, String> named = params.getNamed(); if (named != null) { // Configure updateText if (named.containsKey("update-text")) updateText = named.get("update-text"); // Configure updateLabelStyle if (named.containsKey("update-label-style")) updateLabelStyle = named.get("update-label-style"); // Configure progressBarStyle if (named.containsKey("progress-bar-style")) progressBarStyle = named.get("progress-bar-style"); // Configure wrapperStyle if (named.containsKey("wrapper-style")) wrapperStyle = named.get("wrapper-style"); // Configure cacheDir if (named.containsKey("cache-dir")) cacheDir = named.get("cache-dir"); // Configure acceptDowngrade if (named.containsKey("accept-downgrade")) acceptDowngrade = Boolean.valueOf(named.get("accept-downgrade")); // Configure stopOnUpdateErrors if (named.containsKey("stop-on-update-errors")) stopOnUpdateErrors = Boolean.valueOf(named.get("stop-on-update-errors")); // Configure preload native libraries if (named.containsKey("preload-native-libraries")) preloadNativeLibraries = named.get("preload-native-libraries"); // Should the update screen stay until the primary stage is shown? if (named.containsKey("lingering-update-screen")) lingeringUpdateScreen = Boolean.valueOf(named.get("lingering-update-screen")); // Configure the whats-new option if (named.containsKey("whats-new")) whatsNew = named.get("whats-new"); // Add additional files with these extensions to manifest if (named.containsKey("include-extensions")) includeExtensions.addAll( Arrays.stream(named.get("include-extensions").split(",")) .filter(s -> s != null && !s.isEmpty()) .collect(Collectors.toList()) ); } // Append the rest as manifest parameters StringBuilder rest = new StringBuilder(); for (String raw : params.getRaw()) { // Special case for deprecated parameter. if (raw.equals("--stopOnUpdateErrors")) { stopOnUpdateErrorsDeprecated = true; continue; } if (raw.startsWith("--update-text=")) continue; if (raw.startsWith("--update-label-style=")) continue; if (raw.startsWith("--progress-bar-style=")) continue; if (raw.startsWith("--wrapper-style=")) continue; if (raw.startsWith("--cache-dir=")) continue; if (raw.startsWith("--accept-downgrade=")) continue; if (raw.startsWith("--stop-on-update-errors=")) continue; if (raw.startsWith("--include-extensions=")) continue; if (raw.startsWith("--preload-native-libraries=")) continue; if (raw.startsWith("--whats-new")) continue; if (raw.startsWith("--lingering-update-screen")) continue; if (rest.length() > 0) rest.append(" "); rest.append(raw); } // Add the raw parameter string to the manifest if (rest.length() > 0) parameters = rest.toString(); } FXManifest manifest = create(baseURI, launchClass, appPath); if (updateText != null) manifest.updateText = updateText; if (updateLabelStyle != null) manifest.updateLabelStyle = updateLabelStyle; if (progressBarStyle != null) manifest.progressBarStyle = progressBarStyle; if (wrapperStyle != null) manifest.wrapperStyle = wrapperStyle; if (cacheDir != null) manifest.cacheDir = cacheDir; if (acceptDowngrade != null) manifest.acceptDowngrade = acceptDowngrade; if (parameters != null) manifest.parameters = parameters; if (preloadNativeLibraries != null) manifest.preloadNativeLibraries = preloadNativeLibraries; if (whatsNew != null) manifest.whatsNewPage = whatsNew; manifest.lingeringUpdateScreen = lingeringUpdateScreen; // Use --stop-on-update-errors if it was specified. if (stopOnUpdateErrors != null) { manifest.stopOnUpdateErrors = stopOnUpdateErrors; // If --stopOnUpdateErrors is also present, display warning. if (stopOnUpdateErrorsDeprecated != null) { System.out.println("Warning: --stopOnUpdateErrors is deprecated. " + "Overriding with --stop-on-update-errors."); } } // If --stop-on-update-errors was not specified, // use --stopOnUpdateError if it was specified. else if (stopOnUpdateErrorsDeprecated != null) { manifest.stopOnUpdateErrors = stopOnUpdateErrorsDeprecated; System.out.println("Warning: --stopOnUpdateErrors is deprecated. " + "Use --stop-on-update-errors instead."); } JAXB.marshal(manifest, appPath.resolve("app.xml").toFile()); } public static FXManifest create(URI baseURI, String launchClass, Path appPath) throws IOException, URISyntaxException { FXManifest manifest = new FXManifest(); manifest.ts = System.currentTimeMillis(); manifest.uri = baseURI; manifest.launchClass = launchClass; if (!manifest.uri.getPath().endsWith("/")) { manifest.uri = new URI(String.format("%s/", baseURI.toString())); } Files.walkFileTree(appPath, new SimpleFileVisitor<Path>() { public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (!Files.isDirectory(file) && shouldIncludeInManifest(file) && !file.getFileName().toString().startsWith("fxlauncher")) manifest.files.add(new LibraryFile(appPath, file)); return FileVisitResult.CONTINUE; } }); return manifest; } /** * Add the includeExtensions to the default list of "war" and "jar". * <p> * Although the method is called setIncludeExtensions, it actually does an addAll. * * @param includeExtensions */ public static void setIncludeExtensions(List<String> includeExtensions) { CreateManifest.includeExtensions.addAll(includeExtensions); } private static boolean shouldIncludeInManifest(Path file) { String filename = file.getFileName().toString(); for (String ext : includeExtensions) { if (filename.toLowerCase().endsWith(String.format(".%s", ext.toLowerCase()))) return true; } return false; } }