183 new StandardBundlerParam<>(
184 Arguments.CLIOptions.LINUX_MENU_GROUP.getId(),
185 String.class,
186 params -> I18N.getString("param.menu-group.default"),
187 (s, p) -> s
188 );
189
190 private final static String DEFAULT_ICON = "javalogo_white_32.png";
191 private final static String DEFAULT_CONTROL_TEMPLATE = "template.control";
192 private final static String DEFAULT_PRERM_TEMPLATE = "template.prerm";
193 private final static String DEFAULT_PREINSTALL_TEMPLATE =
194 "template.preinst";
195 private final static String DEFAULT_POSTRM_TEMPLATE = "template.postrm";
196 private final static String DEFAULT_POSTINSTALL_TEMPLATE =
197 "template.postinst";
198 private final static String DEFAULT_COPYRIGHT_TEMPLATE =
199 "template.copyright";
200 private final static String DEFAULT_DESKTOP_FILE_TEMPLATE =
201 "template.desktop";
202
203 public final static String TOOL_DPKG = "dpkg-deb";
204
205 public static boolean testTool(String toolName, String minVersion) {
206 try {
207 ProcessBuilder pb = new ProcessBuilder(
208 toolName,
209 "--version");
210 // not interested in the output
211 IOUtils.exec(pb, true, null);
212 } catch (Exception e) {
213 Log.verbose(MessageFormat.format(I18N.getString(
214 "message.test-for-tool"), toolName, e.getMessage()));
215 return false;
216 }
217 return true;
218 }
219
220 @Override
221 public boolean validate(Map<String, ? super Object> params)
222 throws ConfigException {
223 try {
224 if (params == null) throw new ConfigException(
225 I18N.getString("error.parameters-null"),
226 I18N.getString("error.parameters-null.advice"));
227
228 //run basic validation to ensure requirements are met
229 //we are not interested in return code, only possible exception
230 APP_BUNDLER.fetchFrom(params).validate(params);
231
232 // NOTE: Can we validate that the required tools are available
233 // before we start?
234 if (!testTool(TOOL_DPKG, "1")){
235 throw new ConfigException(MessageFormat.format(
236 I18N.getString("error.tool-not-found"), TOOL_DPKG),
237 I18N.getString("error.tool-not-found.advice"));
238 }
239
240
241 // Show warning is license file is missing
242 String licenseFile = LICENSE_FILE.fetchFrom(params);
243 if (licenseFile == null) {
244 Log.verbose(I18N.getString("message.debs-like-licenses"));
245 }
246
247 // only one mime type per association, at least one file extention
248 List<Map<String, ? super Object>> associations =
249 FILE_ASSOCIATIONS.fetchFrom(params);
250 if (associations != null) {
251 for (int i = 0; i < associations.size(); i++) {
252 Map<String, ? super Object> assoc = associations.get(i);
253 List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc);
337
338 /*
339 * set permissions with a string like "rwxr-xr-x"
340 *
341 * This cannot be directly backport to 22u which is built with 1.6
342 */
343 private void setPermissions(File file, String permissions) {
344 Set<PosixFilePermission> filePermissions =
345 PosixFilePermissions.fromString(permissions);
346 try {
347 if (file.exists()) {
348 Files.setPosixFilePermissions(file.toPath(), filePermissions);
349 }
350 } catch (IOException ex) {
351 Log.error(ex.getMessage());
352 Log.verbose(ex);
353 }
354
355 }
356
357 private String getArch() {
358 String arch = System.getProperty("os.arch");
359 if ("i386".equals(arch))
360 return "i386";
361 else
362 return "amd64";
363 }
364
365 private long getInstalledSizeKB(Map<String, ? super Object> params) {
366 return getInstalledSizeKB(APP_IMAGE_ROOT.fetchFrom(params)) >> 10;
367 }
368
369 private long getInstalledSizeKB(File dir) {
370 long count = 0;
371 File[] children = dir.listFiles();
372 if (children != null) {
373 for (File file : children) {
374 if (file.isFile()) {
375 count += file.length();
376 }
377 else if (file.isDirectory()) {
378 count += getInstalledSizeKB(file);
379 }
380 }
381 }
382 return count;
700 w.write(content);
701 }
702 setPermissions(getConfig_PostrmFile(params), "rwxr-xr-x");
703
704 try (Writer w = Files.newBufferedWriter(
705 getConfig_CopyrightFile(params).toPath())) {
706 String content = preprocessTextResource(
707 getConfig_CopyrightFile(params).getName(),
708 I18N.getString("resource.deb-copyright-file"),
709 DEFAULT_COPYRIGHT_TEMPLATE,
710 data,
711 VERBOSE.fetchFrom(params),
712 RESOURCE_DIR.fetchFrom(params));
713 w.write(content);
714 }
715
716 return true;
717 }
718
719 private Map<String, String> createReplacementData(
720 Map<String, ? super Object> params) {
721 Map<String, String> data = new HashMap<>();
722 String launcher = LinuxAppImageBuilder.getLauncherRelativePath(params);
723
724 data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
725 data.put("APPLICATION_FS_NAME", APP_NAME.fetchFrom(params));
726 data.put("APPLICATION_PACKAGE", BUNDLE_NAME.fetchFrom(params));
727 data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
728 data.put("APPLICATION_MAINTAINER", MAINTAINER.fetchFrom(params));
729 data.put("APPLICATION_VERSION", VERSION.fetchFrom(params));
730 data.put("APPLICATION_LAUNCHER_FILENAME", launcher);
731 data.put("INSTALLATION_DIRECTORY", LINUX_INSTALL_DIR.fetchFrom(params));
732 data.put("XDG_PREFIX", XDG_FILE_PREFIX.fetchFrom(params));
733 data.put("DEPLOY_BUNDLE_CATEGORY", MENU_GROUP.fetchFrom(params));
734 data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
735 data.put("APPLICATION_COPYRIGHT", COPYRIGHT.fetchFrom(params));
736 data.put("APPLICATION_LICENSE_TEXT", LICENSE_TEXT.fetchFrom(params));
737 data.put("APPLICATION_ARCH", getArch());
738 data.put("APPLICATION_INSTALLED_SIZE",
739 Long.toString(getInstalledSizeKB(params)));
740 String deps = LINUX_PACKAGE_DEPENDENCIES.fetchFrom(params);
741 data.put("PACKAGE_DEPENDENCIES",
742 deps.isEmpty() ? "" : "Depends: " + deps);
743 data.put("RUNTIME_INSTALLER", "" +
744 StandardBundlerParam.isRuntimeInstaller(params));
745
746 return data;
747 }
748
749 private File getConfig_DesktopShortcutFile(File rootDir,
750 Map<String, ? super Object> params) {
751 return new File(rootDir, APP_NAME.fetchFrom(params) + ".desktop");
752 }
753
754 private File getConfig_IconFile(File rootDir,
755 Map<String, ? super Object> params) {
756 return new File(rootDir, APP_NAME.fetchFrom(params) + ".png");
757 }
774
775 private File getConfig_PostrmFile(Map<String, ? super Object> params) {
776 return new File(CONFIG_DIR.fetchFrom(params), "postrm");
777 }
778
779 private File getConfig_CopyrightFile(Map<String, ? super Object> params) {
780 return new File(CONFIG_DIR.fetchFrom(params), "copyright");
781 }
782
783 private File buildDeb(Map<String, ? super Object> params,
784 File outdir) throws IOException {
785 File outFile = new File(outdir,
786 FULL_PACKAGE_NAME.fetchFrom(params)+".deb");
787 Log.verbose(MessageFormat.format(I18N.getString(
788 "message.outputting-to-location"), outFile.getAbsolutePath()));
789
790 outFile.getParentFile().mkdirs();
791
792 // run dpkg
793 ProcessBuilder pb = new ProcessBuilder(
794 "fakeroot", TOOL_DPKG, "-b",
795 FULL_PACKAGE_NAME.fetchFrom(params),
796 outFile.getAbsolutePath());
797 pb = pb.directory(DEB_IMAGE_DIR.fetchFrom(params).getParentFile());
798 IOUtils.exec(pb);
799
800 Log.verbose(MessageFormat.format(I18N.getString(
801 "message.output-to-location"), outFile.getAbsolutePath()));
802
803 return outFile;
804 }
805
806 @Override
807 public String getName() {
808 return I18N.getString("deb.bundler.name");
809 }
810
811 @Override
812 public String getID() {
813 return "deb";
814 }
815
816 @Override
817 public String getBundleType() {
818 return "INSTALLER";
819 }
820
821 @Override
822 public File execute(Map<String, ? super Object> params,
823 File outputParentDir) throws PackagerException {
824 return bundle(params, outputParentDir);
825 }
826
827 @Override
828 public boolean supported(boolean runtimeInstaller) {
829 return isSupported();
830 }
831
832 public static boolean isSupported() {
833 if (Platform.getPlatform() == Platform.LINUX) {
834 if (testTool(TOOL_DPKG, "1")) {
835 return true;
836 }
837 }
838 return false;
839 }
840
841 public int getSquareSizeOfImage(File f) {
842 try {
843 BufferedImage bi = ImageIO.read(f);
844 if (bi.getWidth() == bi.getHeight()) {
845 return bi.getWidth();
846 } else {
847 return 0;
848 }
849 } catch (Exception e) {
850 Log.verbose(e);
851 return 0;
852 }
853 }
854 }
|
183 new StandardBundlerParam<>(
184 Arguments.CLIOptions.LINUX_MENU_GROUP.getId(),
185 String.class,
186 params -> I18N.getString("param.menu-group.default"),
187 (s, p) -> s
188 );
189
190 private final static String DEFAULT_ICON = "javalogo_white_32.png";
191 private final static String DEFAULT_CONTROL_TEMPLATE = "template.control";
192 private final static String DEFAULT_PRERM_TEMPLATE = "template.prerm";
193 private final static String DEFAULT_PREINSTALL_TEMPLATE =
194 "template.preinst";
195 private final static String DEFAULT_POSTRM_TEMPLATE = "template.postrm";
196 private final static String DEFAULT_POSTINSTALL_TEMPLATE =
197 "template.postinst";
198 private final static String DEFAULT_COPYRIGHT_TEMPLATE =
199 "template.copyright";
200 private final static String DEFAULT_DESKTOP_FILE_TEMPLATE =
201 "template.desktop";
202
203 private final static String TOOL_DPKG_DEB = "dpkg-deb";
204 private final static String TOOL_DPKG = "dpkg";
205
206 public static boolean testTool(String toolName, String minVersion) {
207 try {
208 ProcessBuilder pb = new ProcessBuilder(
209 toolName,
210 "--version");
211 // not interested in the output
212 IOUtils.exec(pb, true, null);
213 } catch (Exception e) {
214 Log.verbose(MessageFormat.format(I18N.getString(
215 "message.test-for-tool"), toolName, e.getMessage()));
216 return false;
217 }
218 return true;
219 }
220
221 @Override
222 public boolean validate(Map<String, ? super Object> params)
223 throws ConfigException {
224 try {
225 if (params == null) throw new ConfigException(
226 I18N.getString("error.parameters-null"),
227 I18N.getString("error.parameters-null.advice"));
228
229 //run basic validation to ensure requirements are met
230 //we are not interested in return code, only possible exception
231 APP_BUNDLER.fetchFrom(params).validate(params);
232
233 // NOTE: Can we validate that the required tools are available
234 // before we start?
235 if (!testTool(TOOL_DPKG_DEB, "1")){
236 throw new ConfigException(MessageFormat.format(
237 I18N.getString("error.tool-not-found"), TOOL_DPKG_DEB),
238 I18N.getString("error.tool-not-found.advice"));
239 }
240 if (!testTool(TOOL_DPKG, "1")){
241 throw new ConfigException(MessageFormat.format(
242 I18N.getString("error.tool-not-found"), TOOL_DPKG),
243 I18N.getString("error.tool-not-found.advice"));
244 }
245
246
247 // Show warning is license file is missing
248 String licenseFile = LICENSE_FILE.fetchFrom(params);
249 if (licenseFile == null) {
250 Log.verbose(I18N.getString("message.debs-like-licenses"));
251 }
252
253 // only one mime type per association, at least one file extention
254 List<Map<String, ? super Object>> associations =
255 FILE_ASSOCIATIONS.fetchFrom(params);
256 if (associations != null) {
257 for (int i = 0; i < associations.size(); i++) {
258 Map<String, ? super Object> assoc = associations.get(i);
259 List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc);
343
344 /*
345 * set permissions with a string like "rwxr-xr-x"
346 *
347 * This cannot be directly backport to 22u which is built with 1.6
348 */
349 private void setPermissions(File file, String permissions) {
350 Set<PosixFilePermission> filePermissions =
351 PosixFilePermissions.fromString(permissions);
352 try {
353 if (file.exists()) {
354 Files.setPosixFilePermissions(file.toPath(), filePermissions);
355 }
356 } catch (IOException ex) {
357 Log.error(ex.getMessage());
358 Log.verbose(ex);
359 }
360
361 }
362
363 private static String getDebArch() throws IOException {
364 try (var baos = new ByteArrayOutputStream();
365 var ps = new PrintStream(baos)) {
366 var pb = new ProcessBuilder(TOOL_DPKG, "--print-architecture");
367 IOUtils.exec(pb, false, ps);
368 return baos.toString().split("\n", 2)[0];
369 }
370 }
371
372 private long getInstalledSizeKB(Map<String, ? super Object> params) {
373 return getInstalledSizeKB(APP_IMAGE_ROOT.fetchFrom(params)) >> 10;
374 }
375
376 private long getInstalledSizeKB(File dir) {
377 long count = 0;
378 File[] children = dir.listFiles();
379 if (children != null) {
380 for (File file : children) {
381 if (file.isFile()) {
382 count += file.length();
383 }
384 else if (file.isDirectory()) {
385 count += getInstalledSizeKB(file);
386 }
387 }
388 }
389 return count;
707 w.write(content);
708 }
709 setPermissions(getConfig_PostrmFile(params), "rwxr-xr-x");
710
711 try (Writer w = Files.newBufferedWriter(
712 getConfig_CopyrightFile(params).toPath())) {
713 String content = preprocessTextResource(
714 getConfig_CopyrightFile(params).getName(),
715 I18N.getString("resource.deb-copyright-file"),
716 DEFAULT_COPYRIGHT_TEMPLATE,
717 data,
718 VERBOSE.fetchFrom(params),
719 RESOURCE_DIR.fetchFrom(params));
720 w.write(content);
721 }
722
723 return true;
724 }
725
726 private Map<String, String> createReplacementData(
727 Map<String, ? super Object> params) throws IOException {
728 Map<String, String> data = new HashMap<>();
729 String launcher = LinuxAppImageBuilder.getLauncherRelativePath(params);
730
731 data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
732 data.put("APPLICATION_FS_NAME", APP_NAME.fetchFrom(params));
733 data.put("APPLICATION_PACKAGE", BUNDLE_NAME.fetchFrom(params));
734 data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
735 data.put("APPLICATION_MAINTAINER", MAINTAINER.fetchFrom(params));
736 data.put("APPLICATION_VERSION", VERSION.fetchFrom(params));
737 data.put("APPLICATION_LAUNCHER_FILENAME", launcher);
738 data.put("INSTALLATION_DIRECTORY", LINUX_INSTALL_DIR.fetchFrom(params));
739 data.put("XDG_PREFIX", XDG_FILE_PREFIX.fetchFrom(params));
740 data.put("DEPLOY_BUNDLE_CATEGORY", MENU_GROUP.fetchFrom(params));
741 data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
742 data.put("APPLICATION_COPYRIGHT", COPYRIGHT.fetchFrom(params));
743 data.put("APPLICATION_LICENSE_TEXT", LICENSE_TEXT.fetchFrom(params));
744 data.put("APPLICATION_ARCH", getDebArch());
745 data.put("APPLICATION_INSTALLED_SIZE",
746 Long.toString(getInstalledSizeKB(params)));
747 String deps = LINUX_PACKAGE_DEPENDENCIES.fetchFrom(params);
748 data.put("PACKAGE_DEPENDENCIES",
749 deps.isEmpty() ? "" : "Depends: " + deps);
750 data.put("RUNTIME_INSTALLER", "" +
751 StandardBundlerParam.isRuntimeInstaller(params));
752
753 return data;
754 }
755
756 private File getConfig_DesktopShortcutFile(File rootDir,
757 Map<String, ? super Object> params) {
758 return new File(rootDir, APP_NAME.fetchFrom(params) + ".desktop");
759 }
760
761 private File getConfig_IconFile(File rootDir,
762 Map<String, ? super Object> params) {
763 return new File(rootDir, APP_NAME.fetchFrom(params) + ".png");
764 }
781
782 private File getConfig_PostrmFile(Map<String, ? super Object> params) {
783 return new File(CONFIG_DIR.fetchFrom(params), "postrm");
784 }
785
786 private File getConfig_CopyrightFile(Map<String, ? super Object> params) {
787 return new File(CONFIG_DIR.fetchFrom(params), "copyright");
788 }
789
790 private File buildDeb(Map<String, ? super Object> params,
791 File outdir) throws IOException {
792 File outFile = new File(outdir,
793 FULL_PACKAGE_NAME.fetchFrom(params)+".deb");
794 Log.verbose(MessageFormat.format(I18N.getString(
795 "message.outputting-to-location"), outFile.getAbsolutePath()));
796
797 outFile.getParentFile().mkdirs();
798
799 // run dpkg
800 ProcessBuilder pb = new ProcessBuilder(
801 "fakeroot", TOOL_DPKG_DEB, "-b",
802 FULL_PACKAGE_NAME.fetchFrom(params),
803 outFile.getAbsolutePath());
804 pb = pb.directory(DEB_IMAGE_DIR.fetchFrom(params).getParentFile());
805 IOUtils.exec(pb);
806
807 Log.verbose(MessageFormat.format(I18N.getString(
808 "message.output-to-location"), outFile.getAbsolutePath()));
809
810 return outFile;
811 }
812
813 @Override
814 public String getName() {
815 return I18N.getString("deb.bundler.name");
816 }
817
818 @Override
819 public String getID() {
820 return "deb";
821 }
822
823 @Override
824 public String getBundleType() {
825 return "INSTALLER";
826 }
827
828 @Override
829 public File execute(Map<String, ? super Object> params,
830 File outputParentDir) throws PackagerException {
831 return bundle(params, outputParentDir);
832 }
833
834 @Override
835 public boolean supported(boolean runtimeInstaller) {
836 return isSupported();
837 }
838
839 public static boolean isSupported() {
840 if (Platform.getPlatform() == Platform.LINUX) {
841 if (testTool(TOOL_DPKG_DEB, "1")) {
842 return true;
843 }
844 }
845 return false;
846 }
847
848 public int getSquareSizeOfImage(File f) {
849 try {
850 BufferedImage bi = ImageIO.read(f);
851 if (bi.getWidth() == bi.getHeight()) {
852 return bi.getWidth();
853 } else {
854 return 0;
855 }
856 } catch (Exception e) {
857 Log.verbose(e);
858 return 0;
859 }
860 }
861 }
|