32 import java.nio.file.attribute.PosixFilePermission;
33 import java.nio.file.attribute.PosixFilePermissions;
34 import java.text.MessageFormat;
35 import java.util.*;
36 import java.util.logging.Level;
37 import java.util.logging.Logger;
38 import java.util.regex.Matcher;
39 import java.util.regex.Pattern;
40
41 import static jdk.jpackage.internal.StandardBundlerParam.*;
42 import static jdk.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
43 import static jdk.jpackage.internal.LinuxAppBundler.LINUX_PACKAGE_DEPENDENCIES;
44
45 public class LinuxRpmBundler extends AbstractBundler {
46
47 private static final ResourceBundle I18N = ResourceBundle.getBundle(
48 "jdk.jpackage.internal.resources.LinuxResources");
49
50 public static final BundlerParamInfo<LinuxAppBundler> APP_BUNDLER =
51 new StandardBundlerParam<>(
52 I18N.getString("param.rpm-app-bundler.name"),
53 I18N.getString("param.rpm-app-bundler.description"),
54 "linux.app.bundler",
55 LinuxAppBundler.class,
56 params -> new LinuxAppBundler(),
57 null);
58
59 public static final BundlerParamInfo<File> RPM_IMAGE_DIR =
60 new StandardBundlerParam<>(
61 I18N.getString("param.image-dir.name"),
62 I18N.getString("param.image-dir.description"),
63 "linux.rpm.imageDir",
64 File.class,
65 params -> {
66 File imagesRoot = IMAGES_ROOT.fetchFrom(params);
67 if (!imagesRoot.exists()) imagesRoot.mkdirs();
68 return new File(imagesRoot, "linux-rpm.image");
69 },
70 (s, p) -> new File(s));
71
72 // Fedora rules for package naming are used here
73 // https://fedoraproject.org/wiki/Packaging:NamingGuidelines?rd=Packaging/NamingGuidelines
74 //
75 // all Fedora packages must be named using only the following ASCII
76 // characters. These characters are displayed here:
77 //
78 // abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._+
79 //
80 private static final Pattern RPM_BUNDLE_NAME_PATTERN =
81 Pattern.compile("[a-z\\d\\+\\-\\.\\_]+", Pattern.CASE_INSENSITIVE);
82
83 public static final BundlerParamInfo<String> BUNDLE_NAME =
84 new StandardBundlerParam<> (
85 I18N.getString("param.bundle-name.name"),
86 I18N.getString("param.bundle-name.description"),
87 Arguments.CLIOptions.LINUX_BUNDLE_NAME.getId(),
88 String.class,
89 params -> {
90 String nm = APP_NAME.fetchFrom(params);
91 if (nm == null) return null;
92
93 // make sure to lower case and spaces become dashes
94 nm = nm.toLowerCase().replaceAll("[ ]", "-");
95
96 return nm;
97 },
98 (s, p) -> {
99 if (!RPM_BUNDLE_NAME_PATTERN.matcher(s).matches()) {
100 String msgKey = "error.invalid-value-for-package-name";
101 throw new IllegalArgumentException(
102 new ConfigException(MessageFormat.format(
103 I18N.getString(msgKey), s),
104 I18N.getString(msgKey + ".advice")));
105 }
106
107 return s;
108 }
109 );
110
111 public static final BundlerParamInfo<String> LICENSE_TYPE =
112 new StandardBundlerParam<>(
113 I18N.getString("param.license-type.name"),
114 I18N.getString("param.license-type.description"),
115 Arguments.CLIOptions.LINUX_RPM_LICENSE_TYPE.getId(),
116 String.class,
117 params -> I18N.getString("param.license-type.default"),
118 (s, p) -> s
119 );
120
121 public static final BundlerParamInfo<String> XDG_FILE_PREFIX =
122 new StandardBundlerParam<> (
123 I18N.getString("param.xdg-prefix.name"),
124 I18N.getString("param.xdg-prefix.description"),
125 "linux.xdg-prefix",
126 String.class,
127 params -> {
128 try {
129 String vendor;
130 if (params.containsKey(VENDOR.getID())) {
131 vendor = VENDOR.fetchFrom(params);
132 } else {
133 vendor = "jpackage";
134 }
135 String appName = APP_NAME.fetchFrom(params);
136
137 return (vendor + "-" + appName).replaceAll("\\s", "");
138 } catch (Exception e) {
139 if (Log.isDebug()) {
140 e.printStackTrace();
141 }
142 }
143 return "unknown-MimeInfo.xml";
144 },
299 sb.append("%license ");
300 sb.append(LINUX_INSTALL_DIR.fetchFrom(params));
301 sb.append("/");
302 sb.append(APP_NAME.fetchFrom(params));
303 sb.append("/app/");
304 sb.append(licenseFile.getName());
305 }
306
307 return sb.toString();
308 }
309
310 private boolean prepareProjectConfig(Map<String, ? super Object> params)
311 throws IOException {
312 Map<String, String> data = createReplacementData(params);
313 File rootDir =
314 LinuxAppBundler.getRootDir(RPM_IMAGE_DIR.fetchFrom(params), params);
315
316 // prepare installer icon
317 File iconTarget = getConfig_IconFile(rootDir, params);
318 File icon = LinuxAppBundler.ICON_PNG.fetchFrom(params);
319 if (!RUNTIME_INSTALLER.fetchFrom(params)) {
320 if (icon == null || !icon.exists()) {
321 fetchResource(iconTarget.getName(),
322 I18N.getString("resource.menu-icon"),
323 DEFAULT_ICON,
324 iconTarget,
325 VERBOSE.fetchFrom(params),
326 RESOURCE_DIR.fetchFrom(params));
327 } else {
328 fetchResource(iconTarget.getName(),
329 I18N.getString("resource.menu-icon"),
330 icon,
331 iconTarget,
332 VERBOSE.fetchFrom(params),
333 RESOURCE_DIR.fetchFrom(params));
334 }
335 }
336
337 StringBuilder installScripts = new StringBuilder();
338 StringBuilder removeScripts = new StringBuilder();
339 for (Map<String, ? super Object> secondaryLauncher :
340 SECONDARY_LAUNCHERS.fetchFrom(params)) {
341 Map<String, String> secondaryLauncherData =
342 createReplacementData(secondaryLauncher);
343 secondaryLauncherData.put("APPLICATION_FS_NAME",
344 data.get("APPLICATION_FS_NAME"));
345 secondaryLauncherData.put("DESKTOP_MIMES", "");
346
347 // prepare desktop shortcut
348 Writer w = new BufferedWriter(new FileWriter(
349 getConfig_DesktopShortcutFile(rootDir, secondaryLauncher)));
350 String content = preprocessTextResource(
351 getConfig_DesktopShortcutFile(rootDir,
352 secondaryLauncher).getName(),
353 I18N.getString("resource.menu-shortcut-descriptor"),
354 DEFAULT_DESKTOP_FILE_TEMPLATE, secondaryLauncherData,
355 VERBOSE.fetchFrom(params),
356 RESOURCE_DIR.fetchFrom(params));
357 w.write(content);
358 w.close();
359
360 // prepare installer icon
361 iconTarget = getConfig_IconFile(rootDir, secondaryLauncher);
362 icon = LinuxAppBundler.ICON_PNG.fetchFrom(secondaryLauncher);
363 if (icon == null || !icon.exists()) {
364 fetchResource(iconTarget.getName(),
365 I18N.getString("resource.menu-icon"),
366 DEFAULT_ICON,
367 iconTarget,
368 VERBOSE.fetchFrom(params),
369 RESOURCE_DIR.fetchFrom(params));
370 } else {
371 fetchResource(iconTarget.getName(),
372 I18N.getString("resource.menu-icon"),
373 icon,
374 iconTarget,
375 VERBOSE.fetchFrom(params),
376 RESOURCE_DIR.fetchFrom(params));
377 }
378
379 // post copying of desktop icon
380 installScripts.append("xdg-desktop-menu install --novendor ");
381 installScripts.append(LINUX_INSTALL_DIR.fetchFrom(params));
382 installScripts.append("/");
383 installScripts.append(data.get("APPLICATION_FS_NAME"));
384 installScripts.append("/");
385 installScripts.append(secondaryLauncherData.get(
386 "APPLICATION_LAUNCHER_FILENAME"));
387 installScripts.append(".desktop\n");
388
389 // preun cleanup of desktop icon
390 removeScripts.append("xdg-desktop-menu uninstall --novendor ");
391 removeScripts.append(LINUX_INSTALL_DIR.fetchFrom(params));
392 removeScripts.append("/");
393 removeScripts.append(data.get("APPLICATION_FS_NAME"));
394 removeScripts.append("/");
395 removeScripts.append(secondaryLauncherData.get(
396 "APPLICATION_LAUNCHER_FILENAME"));
397 removeScripts.append(".desktop\n");
398
399 }
400 data.put("SECONDARY_LAUNCHERS_INSTALL", installScripts.toString());
401 data.put("SECONDARY_LAUNCHERS_REMOVE", removeScripts.toString());
402
403 StringBuilder cdsScript = new StringBuilder();
404
405 data.put("APP_CDS_CACHE", cdsScript.toString());
406
407 List<Map<String, ? super Object>> associations =
408 FILE_ASSOCIATIONS.fetchFrom(params);
409 data.put("FILE_ASSOCIATION_INSTALL", "");
410 data.put("FILE_ASSOCIATION_REMOVE", "");
411 data.put("DESKTOP_MIMES", "");
412 if (associations != null) {
413 String mimeInfoFile = XDG_FILE_PREFIX.fetchFrom(params)
414 + "-MimeInfo.xml";
415 StringBuilder mimeInfo = new StringBuilder(
416 "<?xml version=\"1.0\"?>\n<mime-info xmlns="
417 +"'http://www.freedesktop.org/standards/shared-mime-info'>\n");
418 StringBuilder registrations = new StringBuilder();
419 StringBuilder deregistrations = new StringBuilder();
420 StringBuilder desktopMimes = new StringBuilder("MimeType=");
421 boolean addedEntry = false;
527 .append(target.getName())
528 .append(" ")
529 .append(dashMime)
530 .append("\n");
531 }
532 }
533 }
534 mimeInfo.append("</mime-info>");
535
536 if (addedEntry) {
537 Writer w = new BufferedWriter(new FileWriter(
538 new File(rootDir, mimeInfoFile)));
539 w.write(mimeInfo.toString());
540 w.close();
541 data.put("FILE_ASSOCIATION_INSTALL", registrations.toString());
542 data.put("FILE_ASSOCIATION_REMOVE", deregistrations.toString());
543 data.put("DESKTOP_MIMES", desktopMimes.toString());
544 }
545 }
546
547 if (!RUNTIME_INSTALLER.fetchFrom(params)) {
548 //prepare desktop shortcut
549 Writer w = new BufferedWriter(new FileWriter(
550 getConfig_DesktopShortcutFile(rootDir, params)));
551 String content = preprocessTextResource(
552 getConfig_DesktopShortcutFile(rootDir, params).getName(),
553 I18N.getString("resource.menu-shortcut-descriptor"),
554 DEFAULT_DESKTOP_FILE_TEMPLATE, data,
555 VERBOSE.fetchFrom(params),
556 RESOURCE_DIR.fetchFrom(params));
557 w.write(content);
558 w.close();
559 }
560
561 // prepare spec file
562 Writer w = new BufferedWriter(
563 new FileWriter(getConfig_SpecFile(params)));
564 String content = preprocessTextResource(
565 getConfig_SpecFile(params).getName(),
566 I18N.getString("resource.rpm-spec-file"),
567 DEFAULT_SPEC_TEMPLATE, data,
568 VERBOSE.fetchFrom(params),
569 RESOURCE_DIR.fetchFrom(params));
570 w.write(content);
571 w.close();
572
573 return true;
574 }
575
576 private Map<String, String> createReplacementData(
577 Map<String, ? super Object> params) throws IOException {
578 Map<String, String> data = new HashMap<>();
579
580 data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
581 data.put("APPLICATION_FS_NAME", APP_NAME.fetchFrom(params));
582 data.put("APPLICATION_PACKAGE", BUNDLE_NAME.fetchFrom(params));
583 data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
584 data.put("APPLICATION_VERSION", VERSION.fetchFrom(params));
585 data.put("APPLICATION_LAUNCHER_FILENAME", APP_NAME.fetchFrom(params));
586 data.put("INSTALLATION_DIRECTORY", LINUX_INSTALL_DIR.fetchFrom(params));
587 data.put("XDG_PREFIX", XDG_FILE_PREFIX.fetchFrom(params));
588 data.put("DEPLOY_BUNDLE_CATEGORY", CATEGORY.fetchFrom(params));
589 // TODO rpm categories
590 data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
591 data.put("APPLICATION_SUMMARY", TITLE.fetchFrom(params));
592 data.put("APPLICATION_LICENSE_TYPE", LICENSE_TYPE.fetchFrom(params));
593 data.put("APPLICATION_LICENSE_FILE", getLicenseFileString(params));
594 String deps = LINUX_PACKAGE_DEPENDENCIES.fetchFrom(params);
595 data.put("PACKAGE_DEPENDENCIES",
596 deps.isEmpty() ? "" : "Requires: " + deps);
597 data.put("RUNTIME_INSTALLER",
598 RUNTIME_INSTALLER.fetchFrom(params).toString());
599 return data;
600 }
601
602 private File getConfig_DesktopShortcutFile(File rootDir,
603 Map<String, ? super Object> params) {
604 return new File(rootDir, APP_NAME.fetchFrom(params) + ".desktop");
605 }
606
607 private File getConfig_IconFile(File rootDir,
608 Map<String, ? super Object> params) {
609 return new File(rootDir, APP_NAME.fetchFrom(params) + ".png");
610 }
611
612 private File getConfig_SpecFile(Map<String, ? super Object> params) {
613 return new File(RPM_IMAGE_DIR.fetchFrom(params),
614 APP_NAME.fetchFrom(params) + ".spec");
615 }
616
617 private File buildRPM(Map<String, ? super Object> params,
618 File outdir) throws IOException {
619 Log.verbose(MessageFormat.format(I18N.getString(
620 "message.outputting-bundle-location"),
621 outdir.getAbsolutePath()));
622
623 File broot = new File(BUILD_ROOT.fetchFrom(params), "rmpbuildroot");
624
625 outdir.mkdirs();
626
627 //run rpmbuild
628 ProcessBuilder pb = new ProcessBuilder(
629 TOOL_RPMBUILD,
630 "-bb", getConfig_SpecFile(params).getAbsolutePath(),
631 "--define", "%_sourcedir "
632 + RPM_IMAGE_DIR.fetchFrom(params).getAbsolutePath(),
633 // save result to output dir
634 "--define", "%_rpmdir " + outdir.getAbsolutePath(),
635 // do not use other system directories to build as current user
636 "--define", "%_topdir " + broot.getAbsolutePath()
637 );
638 pb = pb.directory(RPM_IMAGE_DIR.fetchFrom(params));
639 IOUtils.exec(pb, false);
640
641 Log.verbose(MessageFormat.format(
642 I18N.getString("message.output-bundle-location"),
643 outdir.getAbsolutePath()));
674 public String getID() {
675 return "rpm";
676 }
677
678 @Override
679 public String getBundleType() {
680 return "INSTALLER";
681 }
682
683 @Override
684 public Collection<BundlerParamInfo<?>> getBundleParameters() {
685 Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
686 results.addAll(LinuxAppBundler.getAppBundleParameters());
687 results.addAll(getRpmBundleParameters());
688 return results;
689 }
690
691 public static Collection<BundlerParamInfo<?>> getRpmBundleParameters() {
692 return Arrays.asList(
693 BUNDLE_NAME,
694 CATEGORY,
695 DESCRIPTION,
696 LinuxAppBundler.ICON_PNG,
697 LICENSE_FILE,
698 LICENSE_TYPE,
699 TITLE,
700 VENDOR
701 );
702 }
703
704 @Override
705 public File execute(Map<String, ? super Object> params,
706 File outputParentDir) throws PackagerException {
707 return bundle(params, outputParentDir);
708 }
709
710 @Override
711 public boolean supported(boolean runtimeInstaller) {
712 return (Platform.getPlatform() == Platform.LINUX);
713 }
714
|
32 import java.nio.file.attribute.PosixFilePermission;
33 import java.nio.file.attribute.PosixFilePermissions;
34 import java.text.MessageFormat;
35 import java.util.*;
36 import java.util.logging.Level;
37 import java.util.logging.Logger;
38 import java.util.regex.Matcher;
39 import java.util.regex.Pattern;
40
41 import static jdk.jpackage.internal.StandardBundlerParam.*;
42 import static jdk.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
43 import static jdk.jpackage.internal.LinuxAppBundler.LINUX_PACKAGE_DEPENDENCIES;
44
45 public class LinuxRpmBundler extends AbstractBundler {
46
47 private static final ResourceBundle I18N = ResourceBundle.getBundle(
48 "jdk.jpackage.internal.resources.LinuxResources");
49
50 public static final BundlerParamInfo<LinuxAppBundler> APP_BUNDLER =
51 new StandardBundlerParam<>(
52 "linux.app.bundler",
53 LinuxAppBundler.class,
54 params -> new LinuxAppBundler(),
55 null);
56
57 public static final BundlerParamInfo<File> RPM_IMAGE_DIR =
58 new StandardBundlerParam<>(
59 "linux.rpm.imageDir",
60 File.class,
61 params -> {
62 File imagesRoot = IMAGES_ROOT.fetchFrom(params);
63 if (!imagesRoot.exists()) imagesRoot.mkdirs();
64 return new File(imagesRoot, "linux-rpm.image");
65 },
66 (s, p) -> new File(s));
67
68 // Fedora rules for package naming are used here
69 // https://fedoraproject.org/wiki/Packaging:NamingGuidelines?rd=Packaging/NamingGuidelines
70 //
71 // all Fedora packages must be named using only the following ASCII
72 // characters. These characters are displayed here:
73 //
74 // abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._+
75 //
76 private static final Pattern RPM_BUNDLE_NAME_PATTERN =
77 Pattern.compile("[a-z\\d\\+\\-\\.\\_]+", Pattern.CASE_INSENSITIVE);
78
79 public static final BundlerParamInfo<String> BUNDLE_NAME =
80 new StandardBundlerParam<> (
81 Arguments.CLIOptions.LINUX_BUNDLE_NAME.getId(),
82 String.class,
83 params -> {
84 String nm = APP_NAME.fetchFrom(params);
85 if (nm == null) return null;
86
87 // make sure to lower case and spaces become dashes
88 nm = nm.toLowerCase().replaceAll("[ ]", "-");
89
90 return nm;
91 },
92 (s, p) -> {
93 if (!RPM_BUNDLE_NAME_PATTERN.matcher(s).matches()) {
94 String msgKey = "error.invalid-value-for-package-name";
95 throw new IllegalArgumentException(
96 new ConfigException(MessageFormat.format(
97 I18N.getString(msgKey), s),
98 I18N.getString(msgKey + ".advice")));
99 }
100
101 return s;
102 }
103 );
104
105 public static final BundlerParamInfo<String> MENU_GROUP =
106 new StandardBundlerParam<>(
107 Arguments.CLIOptions.LINUX_MENU_GROUP.getId(),
108 String.class,
109 params -> I18N.getString("param.menu-group.default"),
110 (s, p) -> s
111 );
112
113 public static final BundlerParamInfo<String> LICENSE_TYPE =
114 new StandardBundlerParam<>(
115 Arguments.CLIOptions.LINUX_RPM_LICENSE_TYPE.getId(),
116 String.class,
117 params -> I18N.getString("param.license-type.default"),
118 (s, p) -> s
119 );
120
121 public static final BundlerParamInfo<String> XDG_FILE_PREFIX =
122 new StandardBundlerParam<> (
123 "linux.xdg-prefix",
124 String.class,
125 params -> {
126 try {
127 String vendor;
128 if (params.containsKey(VENDOR.getID())) {
129 vendor = VENDOR.fetchFrom(params);
130 } else {
131 vendor = "jpackage";
132 }
133 String appName = APP_NAME.fetchFrom(params);
134
135 return (vendor + "-" + appName).replaceAll("\\s", "");
136 } catch (Exception e) {
137 if (Log.isDebug()) {
138 e.printStackTrace();
139 }
140 }
141 return "unknown-MimeInfo.xml";
142 },
297 sb.append("%license ");
298 sb.append(LINUX_INSTALL_DIR.fetchFrom(params));
299 sb.append("/");
300 sb.append(APP_NAME.fetchFrom(params));
301 sb.append("/app/");
302 sb.append(licenseFile.getName());
303 }
304
305 return sb.toString();
306 }
307
308 private boolean prepareProjectConfig(Map<String, ? super Object> params)
309 throws IOException {
310 Map<String, String> data = createReplacementData(params);
311 File rootDir =
312 LinuxAppBundler.getRootDir(RPM_IMAGE_DIR.fetchFrom(params), params);
313
314 // prepare installer icon
315 File iconTarget = getConfig_IconFile(rootDir, params);
316 File icon = LinuxAppBundler.ICON_PNG.fetchFrom(params);
317 if (!StandardBundlerParam.isRuntimeInstaller(params)) {
318 if (icon == null || !icon.exists()) {
319 fetchResource(iconTarget.getName(),
320 I18N.getString("resource.menu-icon"),
321 DEFAULT_ICON,
322 iconTarget,
323 VERBOSE.fetchFrom(params),
324 RESOURCE_DIR.fetchFrom(params));
325 } else {
326 fetchResource(iconTarget.getName(),
327 I18N.getString("resource.menu-icon"),
328 icon,
329 iconTarget,
330 VERBOSE.fetchFrom(params),
331 RESOURCE_DIR.fetchFrom(params));
332 }
333 }
334
335 StringBuilder installScripts = new StringBuilder();
336 StringBuilder removeScripts = new StringBuilder();
337 for (Map<String, ? super Object> addLauncher :
338 ADD_LAUNCHERS.fetchFrom(params)) {
339 Map<String, String> addLauncherData =
340 createReplacementData(addLauncher);
341 addLauncherData.put("APPLICATION_FS_NAME",
342 data.get("APPLICATION_FS_NAME"));
343 addLauncherData.put("DESKTOP_MIMES", "");
344
345 // prepare desktop shortcut
346 Writer w = new BufferedWriter(new FileWriter(
347 getConfig_DesktopShortcutFile(rootDir, addLauncher)));
348 String content = preprocessTextResource(
349 getConfig_DesktopShortcutFile(rootDir,
350 addLauncher).getName(),
351 I18N.getString("resource.menu-shortcut-descriptor"),
352 DEFAULT_DESKTOP_FILE_TEMPLATE, addLauncherData,
353 VERBOSE.fetchFrom(params),
354 RESOURCE_DIR.fetchFrom(params));
355 w.write(content);
356 w.close();
357
358 // prepare installer icon
359 iconTarget = getConfig_IconFile(rootDir, addLauncher);
360 icon = LinuxAppBundler.ICON_PNG.fetchFrom(addLauncher);
361 if (icon == null || !icon.exists()) {
362 fetchResource(iconTarget.getName(),
363 I18N.getString("resource.menu-icon"),
364 DEFAULT_ICON,
365 iconTarget,
366 VERBOSE.fetchFrom(params),
367 RESOURCE_DIR.fetchFrom(params));
368 } else {
369 fetchResource(iconTarget.getName(),
370 I18N.getString("resource.menu-icon"),
371 icon,
372 iconTarget,
373 VERBOSE.fetchFrom(params),
374 RESOURCE_DIR.fetchFrom(params));
375 }
376
377 // post copying of desktop icon
378 installScripts.append("xdg-desktop-menu install --novendor ");
379 installScripts.append(LINUX_INSTALL_DIR.fetchFrom(params));
380 installScripts.append("/");
381 installScripts.append(data.get("APPLICATION_FS_NAME"));
382 installScripts.append("/");
383 installScripts.append(addLauncherData.get(
384 "APPLICATION_LAUNCHER_FILENAME"));
385 installScripts.append(".desktop\n");
386
387 // preun cleanup of desktop icon
388 removeScripts.append("xdg-desktop-menu uninstall --novendor ");
389 removeScripts.append(LINUX_INSTALL_DIR.fetchFrom(params));
390 removeScripts.append("/");
391 removeScripts.append(data.get("APPLICATION_FS_NAME"));
392 removeScripts.append("/");
393 removeScripts.append(addLauncherData.get(
394 "APPLICATION_LAUNCHER_FILENAME"));
395 removeScripts.append(".desktop\n");
396
397 }
398 data.put("ADD_LAUNCHERS_INSTALL", installScripts.toString());
399 data.put("ADD_LAUNCHERS_REMOVE", removeScripts.toString());
400
401 StringBuilder cdsScript = new StringBuilder();
402
403 data.put("APP_CDS_CACHE", cdsScript.toString());
404
405 List<Map<String, ? super Object>> associations =
406 FILE_ASSOCIATIONS.fetchFrom(params);
407 data.put("FILE_ASSOCIATION_INSTALL", "");
408 data.put("FILE_ASSOCIATION_REMOVE", "");
409 data.put("DESKTOP_MIMES", "");
410 if (associations != null) {
411 String mimeInfoFile = XDG_FILE_PREFIX.fetchFrom(params)
412 + "-MimeInfo.xml";
413 StringBuilder mimeInfo = new StringBuilder(
414 "<?xml version=\"1.0\"?>\n<mime-info xmlns="
415 +"'http://www.freedesktop.org/standards/shared-mime-info'>\n");
416 StringBuilder registrations = new StringBuilder();
417 StringBuilder deregistrations = new StringBuilder();
418 StringBuilder desktopMimes = new StringBuilder("MimeType=");
419 boolean addedEntry = false;
525 .append(target.getName())
526 .append(" ")
527 .append(dashMime)
528 .append("\n");
529 }
530 }
531 }
532 mimeInfo.append("</mime-info>");
533
534 if (addedEntry) {
535 Writer w = new BufferedWriter(new FileWriter(
536 new File(rootDir, mimeInfoFile)));
537 w.write(mimeInfo.toString());
538 w.close();
539 data.put("FILE_ASSOCIATION_INSTALL", registrations.toString());
540 data.put("FILE_ASSOCIATION_REMOVE", deregistrations.toString());
541 data.put("DESKTOP_MIMES", desktopMimes.toString());
542 }
543 }
544
545 if (!StandardBundlerParam.isRuntimeInstaller(params)) {
546 //prepare desktop shortcut
547 Writer w = new BufferedWriter(new FileWriter(
548 getConfig_DesktopShortcutFile(rootDir, params)));
549 String content = preprocessTextResource(
550 getConfig_DesktopShortcutFile(rootDir, params).getName(),
551 I18N.getString("resource.menu-shortcut-descriptor"),
552 DEFAULT_DESKTOP_FILE_TEMPLATE, data,
553 VERBOSE.fetchFrom(params),
554 RESOURCE_DIR.fetchFrom(params));
555 w.write(content);
556 w.close();
557 }
558
559 // prepare spec file
560 Writer w = new BufferedWriter(
561 new FileWriter(getConfig_SpecFile(params)));
562 String content = preprocessTextResource(
563 getConfig_SpecFile(params).getName(),
564 I18N.getString("resource.rpm-spec-file"),
565 DEFAULT_SPEC_TEMPLATE, data,
566 VERBOSE.fetchFrom(params),
567 RESOURCE_DIR.fetchFrom(params));
568 w.write(content);
569 w.close();
570
571 return true;
572 }
573
574 private Map<String, String> createReplacementData(
575 Map<String, ? super Object> params) throws IOException {
576 Map<String, String> data = new HashMap<>();
577
578 data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
579 data.put("APPLICATION_FS_NAME", APP_NAME.fetchFrom(params));
580 data.put("APPLICATION_PACKAGE", BUNDLE_NAME.fetchFrom(params));
581 data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
582 data.put("APPLICATION_VERSION", VERSION.fetchFrom(params));
583 data.put("APPLICATION_LAUNCHER_FILENAME", APP_NAME.fetchFrom(params));
584 data.put("INSTALLATION_DIRECTORY", LINUX_INSTALL_DIR.fetchFrom(params));
585 data.put("XDG_PREFIX", XDG_FILE_PREFIX.fetchFrom(params));
586 data.put("DEPLOY_BUNDLE_CATEGORY", MENU_GROUP.fetchFrom(params));
587 // TODO rpm categories
588 data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
589 data.put("APPLICATION_SUMMARY", TITLE.fetchFrom(params));
590 data.put("APPLICATION_LICENSE_TYPE", LICENSE_TYPE.fetchFrom(params));
591 data.put("APPLICATION_LICENSE_FILE", getLicenseFileString(params));
592 String deps = LINUX_PACKAGE_DEPENDENCIES.fetchFrom(params);
593 data.put("PACKAGE_DEPENDENCIES",
594 deps.isEmpty() ? "" : "Requires: " + deps);
595 data.put("RUNTIME_INSTALLER", "" +
596 StandardBundlerParam.isRuntimeInstaller(params));
597 return data;
598 }
599
600 private File getConfig_DesktopShortcutFile(File rootDir,
601 Map<String, ? super Object> params) {
602 return new File(rootDir, APP_NAME.fetchFrom(params) + ".desktop");
603 }
604
605 private File getConfig_IconFile(File rootDir,
606 Map<String, ? super Object> params) {
607 return new File(rootDir, APP_NAME.fetchFrom(params) + ".png");
608 }
609
610 private File getConfig_SpecFile(Map<String, ? super Object> params) {
611 return new File(RPM_IMAGE_DIR.fetchFrom(params),
612 APP_NAME.fetchFrom(params) + ".spec");
613 }
614
615 private File buildRPM(Map<String, ? super Object> params,
616 File outdir) throws IOException {
617 Log.verbose(MessageFormat.format(I18N.getString(
618 "message.outputting-bundle-location"),
619 outdir.getAbsolutePath()));
620
621 File broot = new File(TEMP_ROOT.fetchFrom(params), "rmpbuildroot");
622
623 outdir.mkdirs();
624
625 //run rpmbuild
626 ProcessBuilder pb = new ProcessBuilder(
627 TOOL_RPMBUILD,
628 "-bb", getConfig_SpecFile(params).getAbsolutePath(),
629 "--define", "%_sourcedir "
630 + RPM_IMAGE_DIR.fetchFrom(params).getAbsolutePath(),
631 // save result to output dir
632 "--define", "%_rpmdir " + outdir.getAbsolutePath(),
633 // do not use other system directories to build as current user
634 "--define", "%_topdir " + broot.getAbsolutePath()
635 );
636 pb = pb.directory(RPM_IMAGE_DIR.fetchFrom(params));
637 IOUtils.exec(pb, false);
638
639 Log.verbose(MessageFormat.format(
640 I18N.getString("message.output-bundle-location"),
641 outdir.getAbsolutePath()));
672 public String getID() {
673 return "rpm";
674 }
675
676 @Override
677 public String getBundleType() {
678 return "INSTALLER";
679 }
680
681 @Override
682 public Collection<BundlerParamInfo<?>> getBundleParameters() {
683 Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
684 results.addAll(LinuxAppBundler.getAppBundleParameters());
685 results.addAll(getRpmBundleParameters());
686 return results;
687 }
688
689 public static Collection<BundlerParamInfo<?>> getRpmBundleParameters() {
690 return Arrays.asList(
691 BUNDLE_NAME,
692 MENU_GROUP,
693 DESCRIPTION,
694 LinuxAppBundler.ICON_PNG,
695 LICENSE_FILE,
696 LICENSE_TYPE,
697 TITLE,
698 VENDOR
699 );
700 }
701
702 @Override
703 public File execute(Map<String, ? super Object> params,
704 File outputParentDir) throws PackagerException {
705 return bundle(params, outputParentDir);
706 }
707
708 @Override
709 public boolean supported(boolean runtimeInstaller) {
710 return (Platform.getPlatform() == Platform.LINUX);
711 }
712
|