src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebBundler.java
branchJDK-8200758-branch
changeset 58301 e0efb29609bd
parent 58116 93b8c1305de2
child 58303 88453b906981
equal deleted inserted replaced
58172:bf06a1d3aef6 58301:e0efb29609bd
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package jdk.jpackage.internal;
    26 package jdk.jpackage.internal;
    27 
    27 
    28 import javax.imageio.ImageIO;
       
    29 import java.awt.image.BufferedImage;
       
    30 import java.io.*;
    28 import java.io.*;
    31 import java.nio.charset.StandardCharsets;
    29 import java.nio.charset.StandardCharsets;
    32 import java.nio.file.FileVisitResult;
    30 import java.nio.file.FileVisitResult;
    33 import java.nio.file.Files;
    31 import java.nio.file.Files;
    34 import java.nio.file.Path;
    32 import java.nio.file.Path;
    35 import java.nio.file.SimpleFileVisitor;
    33 import java.nio.file.SimpleFileVisitor;
    36 import java.nio.file.StandardCopyOption;
       
    37 import java.nio.file.attribute.BasicFileAttributes;
    34 import java.nio.file.attribute.BasicFileAttributes;
    38 
    35 
    39 import java.nio.file.attribute.PosixFilePermission;
    36 import java.nio.file.attribute.PosixFilePermission;
    40 import java.nio.file.attribute.PosixFilePermissions;
    37 import java.nio.file.attribute.PosixFilePermissions;
    41 import java.text.MessageFormat;
    38 import java.text.MessageFormat;
    42 import java.util.*;
    39 import java.util.*;
    43 import java.util.regex.Pattern;
    40 import java.util.regex.Pattern;
    44 import java.util.stream.Stream;
    41 import java.util.stream.Stream;
    45 
    42 
    46 import static jdk.jpackage.internal.StandardBundlerParam.*;
    43 import static jdk.jpackage.internal.StandardBundlerParam.*;
    47 import static jdk.jpackage.internal.LinuxAppBundler.ICON_PNG;
    44 import static jdk.jpackage.internal.LinuxPackageBundler.I18N;
    48 import static jdk.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
    45 
    49 import static jdk.jpackage.internal.LinuxAppBundler.LINUX_PACKAGE_DEPENDENCIES;
    46 public class LinuxDebBundler extends LinuxPackageBundler {
    50 
       
    51 public class LinuxDebBundler extends AbstractBundler {
       
    52 
       
    53     private static final ResourceBundle I18N = ResourceBundle.getBundle(
       
    54                     "jdk.jpackage.internal.resources.LinuxResources");
       
    55 
       
    56     public static final BundlerParamInfo<LinuxAppBundler> APP_BUNDLER =
       
    57             new StandardBundlerParam<>(
       
    58             "linux.app.bundler",
       
    59             LinuxAppBundler.class,
       
    60             params -> new LinuxAppBundler(),
       
    61             (s, p) -> null);
       
    62 
    47 
    63     // Debian rules for package naming are used here
    48     // Debian rules for package naming are used here
    64     // https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
    49     // https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
    65     //
    50     //
    66     // Package names must consist only of lower case letters (a-z),
    51     // Package names must consist only of lower case letters (a-z),
    67     // digits (0-9), plus (+) and minus (-) signs, and periods (.).
    52     // digits (0-9), plus (+) and minus (-) signs, and periods (.).
    68     // They must be at least two characters long and
    53     // They must be at least two characters long and
    69     // must start with an alphanumeric character.
    54     // must start with an alphanumeric character.
    70     //
    55     //
    71     private static final Pattern DEB_BUNDLE_NAME_PATTERN =
    56     private static final Pattern DEB_PACKAGE_NAME_PATTERN =
    72             Pattern.compile("^[a-z][a-z\\d\\+\\-\\.]+");
    57             Pattern.compile("^[a-z][a-z\\d\\+\\-\\.]+");
    73 
    58 
    74     public static final BundlerParamInfo<String> BUNDLE_NAME =
    59     private static final BundlerParamInfo<String> PACKAGE_NAME =
    75             new StandardBundlerParam<> (
    60             new StandardBundlerParam<> (
    76             Arguments.CLIOptions.LINUX_BUNDLE_NAME.getId(),
    61             Arguments.CLIOptions.LINUX_BUNDLE_NAME.getId(),
    77             String.class,
    62             String.class,
    78             params -> {
    63             params -> {
    79                 String nm = APP_NAME.fetchFrom(params);
    64                 String nm = APP_NAME.fetchFrom(params);
    83                 // make sure to lower case and spaces/underscores become dashes
    68                 // make sure to lower case and spaces/underscores become dashes
    84                 nm = nm.toLowerCase().replaceAll("[ _]", "-");
    69                 nm = nm.toLowerCase().replaceAll("[ _]", "-");
    85                 return nm;
    70                 return nm;
    86             },
    71             },
    87             (s, p) -> {
    72             (s, p) -> {
    88                 if (!DEB_BUNDLE_NAME_PATTERN.matcher(s).matches()) {
    73                 if (!DEB_PACKAGE_NAME_PATTERN.matcher(s).matches()) {
    89                     throw new IllegalArgumentException(new ConfigException(
    74                     throw new IllegalArgumentException(new ConfigException(
    90                             MessageFormat.format(I18N.getString(
    75                             MessageFormat.format(I18N.getString(
    91                             "error.invalid-value-for-package-name"), s),
    76                             "error.invalid-value-for-package-name"), s),
    92                             I18N.getString(
    77                             I18N.getString(
    93                             "error.invalid-value-for-package-name.advice")));
    78                             "error.invalid-value-for-package-name.advice")));
    98 
    83 
    99     private static final BundlerParamInfo<String> FULL_PACKAGE_NAME =
    84     private static final BundlerParamInfo<String> FULL_PACKAGE_NAME =
   100             new StandardBundlerParam<>(
    85             new StandardBundlerParam<>(
   101                     "linux.deb.fullPackageName", String.class, params -> {
    86                     "linux.deb.fullPackageName", String.class, params -> {
   102                         try {
    87                         try {
   103                             return BUNDLE_NAME.fetchFrom(params)
    88                             return PACKAGE_NAME.fetchFrom(params)
   104                             + "_" + VERSION.fetchFrom(params)
    89                             + "_" + VERSION.fetchFrom(params)
   105                             + "-" + RELEASE.fetchFrom(params)
    90                             + "-" + RELEASE.fetchFrom(params)
   106                             + "_" + getDebArch();
    91                             + "_" + getDebArch();
   107                         } catch (IOException ex) {
    92                         } catch (IOException ex) {
   108                             Log.verbose(ex);
    93                             Log.verbose(ex);
   109                             return null;
    94                             return null;
   110                         }
    95                         }
   111                     }, (s, p) -> s);
    96                     }, (s, p) -> s);
   112 
    97 
   113     private static final BundlerParamInfo<File> DEB_IMAGE_DIR =
    98     private static final BundlerParamInfo<String> EMAIL =
   114             new StandardBundlerParam<>(
       
   115             "linux.deb.imageDir",
       
   116             File.class,
       
   117             params -> {
       
   118                 File imagesRoot = IMAGES_ROOT.fetchFrom(params);
       
   119                 if (!imagesRoot.exists()) imagesRoot.mkdirs();
       
   120                 return new File(new File(imagesRoot, "linux-deb.image"),
       
   121                         FULL_PACKAGE_NAME.fetchFrom(params));
       
   122             },
       
   123             (s, p) -> new File(s));
       
   124 
       
   125     public static final BundlerParamInfo<File> APP_IMAGE_ROOT =
       
   126             new StandardBundlerParam<>(
       
   127             "linux.deb.imageRoot",
       
   128             File.class,
       
   129             params -> {
       
   130                 File imageDir = DEB_IMAGE_DIR.fetchFrom(params);
       
   131                 return new File(imageDir, LINUX_INSTALL_DIR.fetchFrom(params));
       
   132             },
       
   133             (s, p) -> new File(s));
       
   134 
       
   135     public static final BundlerParamInfo<File> CONFIG_DIR =
       
   136             new StandardBundlerParam<>(
       
   137             "linux.deb.configDir",
       
   138             File.class,
       
   139             params ->  new File(DEB_IMAGE_DIR.fetchFrom(params), "DEBIAN"),
       
   140             (s, p) -> new File(s));
       
   141 
       
   142     public static final BundlerParamInfo<String> EMAIL =
       
   143             new StandardBundlerParam<> (
    99             new StandardBundlerParam<> (
   144             Arguments.CLIOptions.LINUX_DEB_MAINTAINER.getId(),
   100             Arguments.CLIOptions.LINUX_DEB_MAINTAINER.getId(),
   145             String.class,
   101             String.class,
   146             params -> "Unknown",
   102             params -> "Unknown",
   147             (s, p) -> s);
   103             (s, p) -> s);
   148 
   104 
   149     public static final BundlerParamInfo<String> MAINTAINER =
   105     private static final BundlerParamInfo<String> MAINTAINER =
   150             new StandardBundlerParam<> (
   106             new StandardBundlerParam<> (
   151             BundleParams.PARAM_MAINTAINER,
   107             BundleParams.PARAM_MAINTAINER,
   152             String.class,
   108             String.class,
   153             params -> VENDOR.fetchFrom(params) + " <"
   109             params -> VENDOR.fetchFrom(params) + " <"
   154                     + EMAIL.fetchFrom(params) + ">",
   110                     + EMAIL.fetchFrom(params) + ">",
   155             (s, p) -> s);
   111             (s, p) -> s);
   156 
   112 
   157     public static final BundlerParamInfo<String> SECTION =
   113     private static final BundlerParamInfo<String> SECTION =
   158             new StandardBundlerParam<>(
   114             new StandardBundlerParam<>(
   159             Arguments.CLIOptions.LINUX_CATEGORY.getId(),
   115             Arguments.CLIOptions.LINUX_CATEGORY.getId(),
   160             String.class,
   116             String.class,
   161             params -> "misc",
   117             params -> "misc",
   162             (s, p) -> s);
   118             (s, p) -> s);
   163 
   119 
   164     public static final BundlerParamInfo<String> LICENSE_TEXT =
   120     private static final BundlerParamInfo<String> LICENSE_TEXT =
   165             new StandardBundlerParam<> (
   121             new StandardBundlerParam<> (
   166             "linux.deb.licenseText",
   122             "linux.deb.licenseText",
   167             String.class,
   123             String.class,
   168             params -> {
   124             params -> {
   169                 try {
   125                 try {
   182                 }
   138                 }
   183                 return "Unknown";
   139                 return "Unknown";
   184             },
   140             },
   185             (s, p) -> s);
   141             (s, p) -> s);
   186 
   142 
   187     public static final BundlerParamInfo<String> COPYRIGHT_FILE =
   143     private static final BundlerParamInfo<String> COPYRIGHT_FILE =
   188             new StandardBundlerParam<>(
   144             new StandardBundlerParam<>(
   189             Arguments.CLIOptions.LINUX_DEB_COPYRIGHT_FILE.getId(),
   145             Arguments.CLIOptions.LINUX_DEB_COPYRIGHT_FILE.getId(),
   190             String.class,
   146             String.class,
   191             params -> null,
   147             params -> null,
   192             (s, p) -> s);
   148             (s, p) -> s);
   193 
       
   194     public static final BundlerParamInfo<String> XDG_FILE_PREFIX =
       
   195             new StandardBundlerParam<> (
       
   196             "linux.xdg-prefix",
       
   197             String.class,
       
   198             params -> {
       
   199                 try {
       
   200                     String vendor;
       
   201                     if (params.containsKey(VENDOR.getID())) {
       
   202                         vendor = VENDOR.fetchFrom(params);
       
   203                     } else {
       
   204                         vendor = "jpackage";
       
   205                     }
       
   206                     String appName = APP_NAME.fetchFrom(params);
       
   207 
       
   208                     return (appName + "-" + vendor).replaceAll("\\s", "");
       
   209                 } catch (Exception e) {
       
   210                     Log.verbose(e);
       
   211                 }
       
   212                 return "unknown-MimeInfo.xml";
       
   213             },
       
   214             (s, p) -> s);
       
   215 
       
   216     public static final BundlerParamInfo<String> MENU_GROUP =
       
   217         new StandardBundlerParam<>(
       
   218                 Arguments.CLIOptions.LINUX_MENU_GROUP.getId(),
       
   219                 String.class,
       
   220                 params -> I18N.getString("param.menu-group.default"),
       
   221                 (s, p) -> s
       
   222         );
       
   223 
       
   224     public static final StandardBundlerParam<Boolean> SHORTCUT_HINT =
       
   225         new StandardBundlerParam<>(
       
   226                 Arguments.CLIOptions.LINUX_SHORTCUT_HINT.getId(),
       
   227                 Boolean.class,
       
   228                 params -> false,
       
   229                 (s, p) -> (s == null || "null".equalsIgnoreCase(s))
       
   230                         ? false : Boolean.valueOf(s)
       
   231         );
       
   232 
       
   233     private final static String DEFAULT_ICON = "java32.png";
       
   234     private final static String DEFAULT_CONTROL_TEMPLATE = "template.control";
       
   235     private final static String DEFAULT_PRERM_TEMPLATE = "template.prerm";
       
   236     private final static String DEFAULT_PREINSTALL_TEMPLATE =
       
   237             "template.preinst";
       
   238     private final static String DEFAULT_POSTRM_TEMPLATE = "template.postrm";
       
   239     private final static String DEFAULT_POSTINSTALL_TEMPLATE =
       
   240             "template.postinst";
       
   241     private final static String DEFAULT_COPYRIGHT_TEMPLATE =
       
   242             "template.copyright";
       
   243     private final static String DEFAULT_DESKTOP_FILE_TEMPLATE =
       
   244             "template.desktop";
       
   245 
   149 
   246     private final static String TOOL_DPKG_DEB = "dpkg-deb";
   150     private final static String TOOL_DPKG_DEB = "dpkg-deb";
   247     private final static String TOOL_DPKG = "dpkg";
   151     private final static String TOOL_DPKG = "dpkg";
   248 
   152 
   249     public static boolean testTool(String toolName, String minVersion) {
   153     public static boolean testTool(String toolName, String minVersion) {
   259             return false;
   163             return false;
   260         }
   164         }
   261         return true;
   165         return true;
   262     }
   166     }
   263 
   167 
   264     @Override
   168     public LinuxDebBundler() {
   265     public boolean validate(Map<String, ? super Object> params)
   169         super(PACKAGE_NAME);
       
   170     }
       
   171 
       
   172     @Override
       
   173     public void doValidate(Map<String, ? super Object> params)
   266             throws ConfigException {
   174             throws ConfigException {
   267         try {
   175         // NOTE: Can we validate that the required tools are available
   268             if (params == null) throw new ConfigException(
   176         // before we start?
   269                     I18N.getString("error.parameters-null"),
   177         if (!testTool(TOOL_DPKG_DEB, "1")){
   270                     I18N.getString("error.parameters-null.advice"));
   178             throw new ConfigException(MessageFormat.format(
   271 
   179                     I18N.getString("error.tool-not-found"), TOOL_DPKG_DEB),
   272             //run basic validation to ensure requirements are met
   180                     I18N.getString("error.tool-not-found.advice"));
   273             //we are not interested in return code, only possible exception
   181         }
   274             APP_BUNDLER.fetchFrom(params).validate(params);
   182         if (!testTool(TOOL_DPKG, "1")){
   275 
   183             throw new ConfigException(MessageFormat.format(
   276             // NOTE: Can we validate that the required tools are available
   184                     I18N.getString("error.tool-not-found"), TOOL_DPKG),
   277             // before we start?
   185                     I18N.getString("error.tool-not-found.advice"));
   278             if (!testTool(TOOL_DPKG_DEB, "1")){
   186         }
   279                 throw new ConfigException(MessageFormat.format(
   187 
   280                         I18N.getString("error.tool-not-found"), TOOL_DPKG_DEB),
   188 
   281                         I18N.getString("error.tool-not-found.advice"));
   189         // Show warning is license file is missing
   282             }
   190         String licenseFile = LICENSE_FILE.fetchFrom(params);
   283             if (!testTool(TOOL_DPKG, "1")){
   191         if (licenseFile == null) {
   284                 throw new ConfigException(MessageFormat.format(
   192             Log.verbose(I18N.getString("message.debs-like-licenses"));
   285                         I18N.getString("error.tool-not-found"), TOOL_DPKG),
   193         }
   286                         I18N.getString("error.tool-not-found.advice"));
   194     }
   287             }
   195 
   288 
   196     @Override
   289 
   197     protected File buildPackageBundle(
   290             // Show warning is license file is missing
   198             Map<String, String> replacementData,
   291             String licenseFile = LICENSE_FILE.fetchFrom(params);
   199             Map<String, ? super Object> params, File outputParentDir) throws
   292             if (licenseFile == null) {
   200             PackagerException, IOException {
   293                 Log.verbose(I18N.getString("message.debs-like-licenses"));
   201 
   294             }
   202         prepareProjectConfig(replacementData, params);
   295 
   203         adjustPermissionsRecursive(createMetaPackage(params).sourceRoot().toFile());
   296             // only one mime type per association, at least one file extention
   204         return buildDeb(params, outputParentDir);
   297             List<Map<String, ? super Object>> associations =
       
   298                     FILE_ASSOCIATIONS.fetchFrom(params);
       
   299             if (associations != null) {
       
   300                 for (int i = 0; i < associations.size(); i++) {
       
   301                     Map<String, ? super Object> assoc = associations.get(i);
       
   302                     List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc);
       
   303                     if (mimes == null || mimes.isEmpty()) {
       
   304                         String msgKey =
       
   305                             "error.no-content-types-for-file-association";
       
   306                         throw new ConfigException(
       
   307                                 MessageFormat.format(I18N.getString(msgKey), i),
       
   308                                 I18N.getString(msgKey + ".advise"));
       
   309 
       
   310                     } else if (mimes.size() > 1) {
       
   311                         String msgKey =
       
   312                             "error.too-many-content-types-for-file-association";
       
   313                         throw new ConfigException(
       
   314                                 MessageFormat.format(I18N.getString(msgKey), i),
       
   315                                 I18N.getString(msgKey + ".advise"));
       
   316                     }
       
   317                 }
       
   318             }
       
   319 
       
   320             // bundle name has some restrictions
       
   321             // the string converter will throw an exception if invalid
       
   322             BUNDLE_NAME.getStringConverter().apply(
       
   323                     BUNDLE_NAME.fetchFrom(params), params);
       
   324 
       
   325             return true;
       
   326         } catch (RuntimeException re) {
       
   327             if (re.getCause() instanceof ConfigException) {
       
   328                 throw (ConfigException) re.getCause();
       
   329             } else {
       
   330                 throw new ConfigException(re);
       
   331             }
       
   332         }
       
   333     }
       
   334 
       
   335     private boolean prepareProto(Map<String, ? super Object> params)
       
   336             throws PackagerException, IOException {
       
   337         File appImage = StandardBundlerParam.getPredefinedAppImage(params);
       
   338 
       
   339         // we either have an application image or need to build one
       
   340         if (appImage != null) {
       
   341             // copy everything from appImage dir into appDir/name
       
   342             IOUtils.copyRecursive(appImage.toPath(),
       
   343                     getConfig_RootDirectory(params).toPath());
       
   344         } else {
       
   345             File bundleDir = APP_BUNDLER.fetchFrom(params).doBundle(params,
       
   346                     APP_IMAGE_ROOT.fetchFrom(params), true);
       
   347             if (bundleDir == null) {
       
   348                 return false;
       
   349             }
       
   350             Files.move(bundleDir.toPath(), getConfig_RootDirectory(
       
   351                     params).toPath(), StandardCopyOption.REPLACE_EXISTING);
       
   352         }
       
   353         return true;
       
   354     }
       
   355 
       
   356     public File bundle(Map<String, ? super Object> params,
       
   357             File outdir) throws PackagerException {
       
   358 
       
   359         IOUtils.writableOutputDir(outdir.toPath());
       
   360 
       
   361         // we want to create following structure
       
   362         //   <package-name>
       
   363         //        DEBIAN
       
   364         //          control   (file with main package details)
       
   365         //          menu      (request to create menu)
       
   366         //          ... other control files if needed ....
       
   367         //        opt  (by default)
       
   368         //          AppFolder (this is where app image goes)
       
   369         //             launcher executable
       
   370         //             app
       
   371         //             runtime
       
   372 
       
   373         File imageDir = DEB_IMAGE_DIR.fetchFrom(params);
       
   374         File configDir = CONFIG_DIR.fetchFrom(params);
       
   375 
       
   376         try {
       
   377 
       
   378             imageDir.mkdirs();
       
   379             configDir.mkdirs();
       
   380             if (prepareProto(params) && prepareProjectConfig(params)) {
       
   381                 adjustPermissionsRecursive(imageDir);
       
   382                 return buildDeb(params, outdir);
       
   383             }
       
   384             return null;
       
   385         } catch (IOException ex) {
       
   386             Log.verbose(ex);
       
   387             throw new PackagerException(ex);
       
   388         }
       
   389     }
   205     }
   390 
   206 
   391     /*
   207     /*
   392      * set permissions with a string like "rwxr-xr-x"
   208      * set permissions with a string like "rwxr-xr-x"
   393      *
   209      *
   425             return (ret == 0);
   241             return (ret == 0);
   426         } catch (IOException | InterruptedException e) {
   242         } catch (IOException | InterruptedException e) {
   427             // just fall thru
   243             // just fall thru
   428         }
   244         }
   429         return false;
   245         return false;
   430     }
       
   431 
       
   432     private long getInstalledSizeKB(Map<String, ? super Object> params) {
       
   433         return getInstalledSizeKB(APP_IMAGE_ROOT.fetchFrom(params)) >> 10;
       
   434     }
       
   435 
       
   436     private long getInstalledSizeKB(File dir) {
       
   437         long count = 0;
       
   438         File[] children = dir.listFiles();
       
   439         if (children != null) {
       
   440             for (File file : children) {
       
   441                 if (file.isFile()) {
       
   442                     count += file.length();
       
   443                 }
       
   444                 else if (file.isDirectory()) {
       
   445                     count += getInstalledSizeKB(file);
       
   446                 }
       
   447             }
       
   448         }
       
   449         return count;
       
   450     }
   246     }
   451 
   247 
   452     private void adjustPermissionsRecursive(File dir) throws IOException {
   248     private void adjustPermissionsRecursive(File dir) throws IOException {
   453         Files.walkFileTree(dir.toPath(), new SimpleFileVisitor<Path>() {
   249         Files.walkFileTree(dir.toPath(), new SimpleFileVisitor<Path>() {
   454             @Override
   250             @Override
   475                 }
   271                 }
   476             }
   272             }
   477         });
   273         });
   478     }
   274     }
   479 
   275 
   480     private boolean prepareProjectConfig(Map<String, ? super Object> params)
   276     private class DebianFile {
   481             throws IOException {
   277 
   482         Map<String, String> data = createReplacementData(params);
   278         DebianFile(Path dstFilePath, String comment) {
   483         File rootDir = getConfig_RootDirectory(params);
   279             this.dstFilePath = dstFilePath;
   484         File binDir = new File(rootDir, "bin");
   280             this.comment = comment;
   485 
   281         }
   486         File iconTarget = getConfig_IconFile(binDir, params);
   282 
   487         File icon = ICON_PNG.fetchFrom(params);
   283         DebianFile setExecutable() {
   488         if (!StandardBundlerParam.isRuntimeInstaller(params)) {
   284             permissions = "rwxr-xr-x";
   489             // prepare installer icon
   285             return this;
   490             if (icon == null || !icon.exists()) {
   286         }
   491                 fetchResource(iconTarget.getName(),
   287 
   492                         I18N.getString("resource.menu-icon"),
   288         void create(Map<String, String> data, Map<String, ? super Object> params)
   493                         DEFAULT_ICON,
   289                 throws IOException {
   494                         iconTarget,
   290             Files.createDirectories(dstFilePath.getParent());
   495                         VERBOSE.fetchFrom(params),
   291             try (Writer w = Files.newBufferedWriter(dstFilePath)) {
   496                         RESOURCE_DIR.fetchFrom(params));
   292                 String content = preprocessTextResource(
   497             } else {
   293                         dstFilePath.getFileName().toString(),
   498                 fetchResource(iconTarget.getName(),
   294                         I18N.getString(comment),
   499                         I18N.getString("resource.menu-icon"),
   295                         "template." + dstFilePath.getFileName().toString(),
   500                         icon,
       
   501                         iconTarget,
       
   502                         VERBOSE.fetchFrom(params),
       
   503                         RESOURCE_DIR.fetchFrom(params));
       
   504             }
       
   505         }
       
   506 
       
   507         StringBuilder installScripts = new StringBuilder();
       
   508         StringBuilder removeScripts = new StringBuilder();
       
   509         for (Map<String, ? super Object> addLauncher :
       
   510                 ADD_LAUNCHERS.fetchFrom(params)) {
       
   511             Map<String, String> addLauncherData =
       
   512                     createReplacementData(addLauncher);
       
   513             addLauncherData.put("APPLICATION_FS_NAME",
       
   514                     data.get("APPLICATION_FS_NAME"));
       
   515             addLauncherData.put("DESKTOP_MIMES", "");
       
   516 
       
   517             if (!StandardBundlerParam.isRuntimeInstaller(params)) {
       
   518                 // prepare desktop shortcut
       
   519                 if (SHORTCUT_HINT.fetchFrom(params)) {
       
   520                     try (Writer w = Files.newBufferedWriter(
       
   521                         getConfig_DesktopShortcutFile(
       
   522                                 binDir, addLauncher).toPath())) {
       
   523                         String content = preprocessTextResource(
       
   524                             getConfig_DesktopShortcutFile(binDir,
       
   525                             addLauncher).getName(),
       
   526                             I18N.getString("resource.menu-shortcut-descriptor"),
       
   527                             DEFAULT_DESKTOP_FILE_TEMPLATE,
       
   528                             addLauncherData,
       
   529                             VERBOSE.fetchFrom(params),
       
   530                             RESOURCE_DIR.fetchFrom(params));
       
   531                         w.write(content);
       
   532                     }
       
   533                 }
       
   534             }
       
   535 
       
   536             // prepare installer icon
       
   537             iconTarget = getConfig_IconFile(binDir, addLauncher);
       
   538             icon = ICON_PNG.fetchFrom(addLauncher);
       
   539             if (icon == null || !icon.exists()) {
       
   540                 fetchResource(iconTarget.getName(),
       
   541                         I18N.getString("resource.menu-icon"),
       
   542                         DEFAULT_ICON,
       
   543                         iconTarget,
       
   544                         VERBOSE.fetchFrom(params),
       
   545                         RESOURCE_DIR.fetchFrom(params));
       
   546             } else {
       
   547                 fetchResource(iconTarget.getName(),
       
   548                         I18N.getString("resource.menu-icon"),
       
   549                         icon,
       
   550                         iconTarget,
       
   551                         VERBOSE.fetchFrom(params),
       
   552                         RESOURCE_DIR.fetchFrom(params));
       
   553             }
       
   554 
       
   555             // postinst copying of desktop icon
       
   556             installScripts.append(
       
   557                     "        xdg-desktop-menu install --novendor ");
       
   558             installScripts.append(LINUX_INSTALL_DIR.fetchFrom(params));
       
   559             installScripts.append("/");
       
   560             installScripts.append(data.get("APPLICATION_FS_NAME"));
       
   561             installScripts.append("/bin/");
       
   562             installScripts.append(
       
   563                     addLauncherData.get("APPLICATION_LAUNCHER_FILENAME"));
       
   564             installScripts.append(".desktop\n");
       
   565 
       
   566             // postrm cleanup of desktop icon
       
   567             removeScripts.append(
       
   568                     "        xdg-desktop-menu uninstall --novendor ");
       
   569             removeScripts.append(LINUX_INSTALL_DIR.fetchFrom(params));
       
   570             removeScripts.append("/");
       
   571             removeScripts.append(data.get("APPLICATION_FS_NAME"));
       
   572             removeScripts.append("/bin/");
       
   573             removeScripts.append(
       
   574                     addLauncherData.get("APPLICATION_LAUNCHER_FILENAME"));
       
   575             removeScripts.append(".desktop\n");
       
   576         }
       
   577         data.put("ADD_LAUNCHERS_INSTALL", installScripts.toString());
       
   578         data.put("ADD_LAUNCHERS_REMOVE", removeScripts.toString());
       
   579 
       
   580         List<Map<String, ? super Object>> associations =
       
   581                 FILE_ASSOCIATIONS.fetchFrom(params);
       
   582         data.put("FILE_ASSOCIATION_INSTALL", "");
       
   583         data.put("FILE_ASSOCIATION_REMOVE", "");
       
   584         data.put("DESKTOP_MIMES", "");
       
   585         if (associations != null) {
       
   586             String mimeInfoFile = XDG_FILE_PREFIX.fetchFrom(params)
       
   587                     + "-MimeInfo.xml";
       
   588             StringBuilder mimeInfo = new StringBuilder(
       
   589                 "<?xml version=\"1.0\"?>\n<mime-info xmlns="
       
   590                 + "'http://www.freedesktop.org/standards/shared-mime-info'>\n");
       
   591             StringBuilder registrations = new StringBuilder();
       
   592             StringBuilder deregistrations = new StringBuilder();
       
   593             StringBuilder desktopMimes = new StringBuilder("MimeType=");
       
   594             boolean addedEntry = false;
       
   595 
       
   596             for (Map<String, ? super Object> assoc : associations) {
       
   597                 //  <mime-type type="application/x-vnd.awesome">
       
   598                 //    <comment>Awesome document</comment>
       
   599                 //    <glob pattern="*.awesome"/>
       
   600                 //    <glob pattern="*.awe"/>
       
   601                 //  </mime-type>
       
   602 
       
   603                 if (assoc == null) {
       
   604                     continue;
       
   605                 }
       
   606 
       
   607                 String description = FA_DESCRIPTION.fetchFrom(assoc);
       
   608                 File faIcon = FA_ICON.fetchFrom(assoc);
       
   609                 List<String> extensions = FA_EXTENSIONS.fetchFrom(assoc);
       
   610                 if (extensions == null) {
       
   611                     Log.error(I18N.getString(
       
   612                           "message.creating-association-with-null-extension"));
       
   613                 }
       
   614 
       
   615                 List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc);
       
   616                 if (mimes == null || mimes.isEmpty()) {
       
   617                     continue;
       
   618                 }
       
   619                 String thisMime = mimes.get(0);
       
   620                 String dashMime = thisMime.replace('/', '-');
       
   621 
       
   622                 mimeInfo.append("  <mime-type type='")
       
   623                         .append(thisMime)
       
   624                         .append("'>\n");
       
   625                 if (description != null && !description.isEmpty()) {
       
   626                     mimeInfo.append("    <comment>")
       
   627                             .append(description)
       
   628                             .append("</comment>\n");
       
   629                 }
       
   630 
       
   631                 if (extensions != null) {
       
   632                     for (String ext : extensions) {
       
   633                         mimeInfo.append("    <glob pattern='*.")
       
   634                                 .append(ext)
       
   635                                 .append("'/>\n");
       
   636                     }
       
   637                 }
       
   638 
       
   639                 mimeInfo.append("  </mime-type>\n");
       
   640                 if (!addedEntry) {
       
   641                     registrations.append("        xdg-mime install ")
       
   642                             .append(LINUX_INSTALL_DIR.fetchFrom(params))
       
   643                             .append("/")
       
   644                             .append(data.get("APPLICATION_FS_NAME"))
       
   645                             .append("/bin/")
       
   646                             .append(mimeInfoFile)
       
   647                             .append("\n");
       
   648 
       
   649                     deregistrations.append("        xdg-mime uninstall ")
       
   650                             .append(LINUX_INSTALL_DIR.fetchFrom(params))
       
   651                             .append("/")
       
   652                             .append(data.get("APPLICATION_FS_NAME"))
       
   653                             .append("/bin/")
       
   654                             .append(mimeInfoFile)
       
   655                             .append("\n");
       
   656                     addedEntry = true;
       
   657                 } else {
       
   658                     desktopMimes.append(";");
       
   659                 }
       
   660                 desktopMimes.append(thisMime);
       
   661 
       
   662                 if (faIcon != null && faIcon.exists()) {
       
   663                     int size = getSquareSizeOfImage(faIcon);
       
   664 
       
   665                     if (size > 0) {
       
   666                         File target = new File(binDir,
       
   667                                 APP_NAME.fetchFrom(params)
       
   668                                 + "_fa_" + faIcon.getName());
       
   669                         IOUtils.copyFile(faIcon, target);
       
   670 
       
   671                         // xdg-icon-resource install --context mimetypes
       
   672                         // --size 64 awesomeapp_fa_1.png
       
   673                         // application-x.vnd-awesome
       
   674                         registrations.append(
       
   675                                 "        xdg-icon-resource install "
       
   676                                         + "--context mimetypes --size ")
       
   677                                 .append(size)
       
   678                                 .append(" ")
       
   679                                 .append(LINUX_INSTALL_DIR.fetchFrom(params))
       
   680                                 .append("/")
       
   681                                 .append(data.get("APPLICATION_FS_NAME"))
       
   682                                 .append("/")
       
   683                                 .append(target.getName())
       
   684                                 .append(" ")
       
   685                                 .append(dashMime)
       
   686                                 .append("\n");
       
   687 
       
   688                         // x dg-icon-resource uninstall --context mimetypes
       
   689                         // --size 64 awesomeapp_fa_1.png
       
   690                         // application-x.vnd-awesome
       
   691                         deregistrations.append(
       
   692                                 "        xdg-icon-resource uninstall "
       
   693                                         + "--context mimetypes --size ")
       
   694                                 .append(size)
       
   695                                 .append(" ")
       
   696                                 .append(LINUX_INSTALL_DIR.fetchFrom(params))
       
   697                                 .append("/")
       
   698                                 .append(data.get("APPLICATION_FS_NAME"))
       
   699                                 .append("/")
       
   700                                 .append(target.getName())
       
   701                                 .append(" ")
       
   702                                 .append(dashMime)
       
   703                                 .append("\n");
       
   704                     }
       
   705                 }
       
   706             }
       
   707             mimeInfo.append("</mime-info>");
       
   708 
       
   709             if (addedEntry) {
       
   710                 try (Writer w = Files.newBufferedWriter(
       
   711                         new File(binDir, mimeInfoFile).toPath())) {
       
   712                     w.write(mimeInfo.toString());
       
   713                 }
       
   714                 data.put("FILE_ASSOCIATION_INSTALL", registrations.toString());
       
   715                 data.put("FILE_ASSOCIATION_REMOVE", deregistrations.toString());
       
   716                 data.put("DESKTOP_MIMES", desktopMimes.toString());
       
   717             }
       
   718         }
       
   719 
       
   720         if (!StandardBundlerParam.isRuntimeInstaller(params)) {
       
   721             // prepare desktop shortcut
       
   722             if (SHORTCUT_HINT.fetchFrom(params)) {
       
   723                 try (Writer w = Files.newBufferedWriter(
       
   724                     getConfig_DesktopShortcutFile(binDir, params).toPath())) {
       
   725                     String content = preprocessTextResource(
       
   726                         getConfig_DesktopShortcutFile(
       
   727                         binDir, params).getName(),
       
   728                         I18N.getString("resource.menu-shortcut-descriptor"),
       
   729                         DEFAULT_DESKTOP_FILE_TEMPLATE,
       
   730                         data,
   296                         data,
   731                         VERBOSE.fetchFrom(params),
   297                         VERBOSE.fetchFrom(params),
   732                         RESOURCE_DIR.fetchFrom(params));
   298                         RESOURCE_DIR.fetchFrom(params));
   733                     w.write(content);
   299                 w.write(content);
   734                 }
   300             }
   735             }
   301             if (permissions != null) {
   736         }
   302                 setPermissions(dstFilePath.toFile(), permissions);
   737         // prepare control file
   303             }
   738         try (Writer w = Files.newBufferedWriter(
   304         }
   739                 getConfig_ControlFile(params).toPath())) {
   305 
   740             String content = preprocessTextResource(
   306         private final Path dstFilePath;
   741                     getConfig_ControlFile(params).getName(),
   307         private final String comment;
   742                     I18N.getString("resource.deb-control-file"),
   308         private String permissions;
   743                     DEFAULT_CONTROL_TEMPLATE,
   309     }
   744                     data,
   310 
   745                     VERBOSE.fetchFrom(params),
   311     private void prepareProjectConfig(Map<String, String> data,
   746                     RESOURCE_DIR.fetchFrom(params));
   312             Map<String, ? super Object> params) throws IOException {
   747             w.write(content);
   313 
   748         }
   314         Path configDir = createMetaPackage(params).sourceRoot().resolve("DEBIAN");
   749 
   315         List<DebianFile> debianFiles = new ArrayList<>();
   750         try (Writer w = Files.newBufferedWriter(
   316         debianFiles.add(new DebianFile(
   751                 getConfig_PreinstallFile(params).toPath())) {
   317                 configDir.resolve("control"),
   752             String content = preprocessTextResource(
   318                 "resource.deb-control-file"));
   753                     getConfig_PreinstallFile(params).getName(),
   319         debianFiles.add(new DebianFile(
   754                     I18N.getString("resource.deb-preinstall-script"),
   320                 configDir.resolve("preinst"),
   755                     DEFAULT_PREINSTALL_TEMPLATE,
   321                 "resource.deb-preinstall-script").setExecutable());
   756                     data,
   322         debianFiles.add(new DebianFile(
   757                     VERBOSE.fetchFrom(params),
   323                 configDir.resolve("prerm"),
   758                     RESOURCE_DIR.fetchFrom(params));
   324                 "resource.deb-prerm-script").setExecutable());
   759             w.write(content);
   325         debianFiles.add(new DebianFile(
   760         }
   326                 configDir.resolve("postinst"),
   761         setPermissions(getConfig_PreinstallFile(params), "rwxr-xr-x");
   327                 "resource.deb-postinstall-script").setExecutable());
   762 
   328         debianFiles.add(new DebianFile(
   763         try (Writer w = Files.newBufferedWriter(
   329                 configDir.resolve("postrm"),
   764                     getConfig_PrermFile(params).toPath())) {
   330                 "resource.deb-postrm-script").setExecutable());
   765             String content = preprocessTextResource(
       
   766                     getConfig_PrermFile(params).getName(),
       
   767                     I18N.getString("resource.deb-prerm-script"),
       
   768                     DEFAULT_PRERM_TEMPLATE,
       
   769                     data,
       
   770                     VERBOSE.fetchFrom(params),
       
   771                     RESOURCE_DIR.fetchFrom(params));
       
   772             w.write(content);
       
   773         }
       
   774         setPermissions(getConfig_PrermFile(params), "rwxr-xr-x");
       
   775 
       
   776         try (Writer w = Files.newBufferedWriter(
       
   777                 getConfig_PostinstallFile(params).toPath())) {
       
   778             String content = preprocessTextResource(
       
   779                     getConfig_PostinstallFile(params).getName(),
       
   780                     I18N.getString("resource.deb-postinstall-script"),
       
   781                     DEFAULT_POSTINSTALL_TEMPLATE,
       
   782                     data,
       
   783                     VERBOSE.fetchFrom(params),
       
   784                     RESOURCE_DIR.fetchFrom(params));
       
   785             w.write(content);
       
   786         }
       
   787         setPermissions(getConfig_PostinstallFile(params), "rwxr-xr-x");
       
   788 
       
   789         try (Writer w = Files.newBufferedWriter(
       
   790                 getConfig_PostrmFile(params).toPath())) {
       
   791             String content = preprocessTextResource(
       
   792                     getConfig_PostrmFile(params).getName(),
       
   793                     I18N.getString("resource.deb-postrm-script"),
       
   794                     DEFAULT_POSTRM_TEMPLATE,
       
   795                     data,
       
   796                     VERBOSE.fetchFrom(params),
       
   797                     RESOURCE_DIR.fetchFrom(params));
       
   798             w.write(content);
       
   799         }
       
   800         setPermissions(getConfig_PostrmFile(params), "rwxr-xr-x");
       
   801 
   331 
   802         getConfig_CopyrightFile(params).getParentFile().mkdirs();
   332         getConfig_CopyrightFile(params).getParentFile().mkdirs();
   803         String customCopyrightFile = COPYRIGHT_FILE.fetchFrom(params);
   333         String customCopyrightFile = COPYRIGHT_FILE.fetchFrom(params);
   804         if (customCopyrightFile != null) {
   334         if (customCopyrightFile != null) {
   805             IOUtils.copyFile(new File(customCopyrightFile),
   335             IOUtils.copyFile(new File(customCopyrightFile),
   806                     getConfig_CopyrightFile(params));
   336                     getConfig_CopyrightFile(params));
   807         } else {
   337         } else {
   808             try (Writer w = Files.newBufferedWriter(
   338             debianFiles.add(new DebianFile(
   809                     getConfig_CopyrightFile(params).toPath())) {
   339                     getConfig_CopyrightFile(params).toPath(),
   810                 String content = preprocessTextResource(
   340                     "resource.copyright-file"));
   811                         getConfig_CopyrightFile(params).getName(),
   341         }
   812                         I18N.getString("resource.copyright-file"),
   342 
   813                         DEFAULT_COPYRIGHT_TEMPLATE,
   343         for (DebianFile debianFile : debianFiles) {
   814                         data,
   344             debianFile.create(data, params);
   815                         VERBOSE.fetchFrom(params),
   345         }
   816                         RESOURCE_DIR.fetchFrom(params));
   346     }
   817                 w.write(content);
   347 
   818             }
   348     @Override
   819         }
   349     protected Map<String, String> createReplacementData(
   820 
       
   821         return true;
       
   822     }
       
   823 
       
   824     private Map<String, String> createReplacementData(
       
   825             Map<String, ? super Object> params) throws IOException {
   350             Map<String, ? super Object> params) throws IOException {
   826         Map<String, String> data = new HashMap<>();
   351         Map<String, String> data = new HashMap<>();
   827         String launcher = LinuxAppImageBuilder.getLauncherRelativePath(params);
   352 
   828 
       
   829         data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
       
   830         data.put("APPLICATION_FS_NAME",
       
   831                 getConfig_RootDirectory(params).getName());
       
   832         data.put("APPLICATION_PACKAGE", BUNDLE_NAME.fetchFrom(params));
       
   833         data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
       
   834         data.put("APPLICATION_MAINTAINER", MAINTAINER.fetchFrom(params));
   353         data.put("APPLICATION_MAINTAINER", MAINTAINER.fetchFrom(params));
   835         data.put("APPLICATION_VERSION", VERSION.fetchFrom(params));
       
   836         data.put("APPLICATION_RELEASE", RELEASE.fetchFrom(params));
       
   837         data.put("APPLICATION_SECTION", SECTION.fetchFrom(params));
   354         data.put("APPLICATION_SECTION", SECTION.fetchFrom(params));
   838         data.put("APPLICATION_LAUNCHER_FILENAME", launcher);
       
   839         data.put("INSTALLATION_DIRECTORY", LINUX_INSTALL_DIR.fetchFrom(params));
       
   840         data.put("XDG_PREFIX", XDG_FILE_PREFIX.fetchFrom(params));
       
   841         data.put("DEPLOY_BUNDLE_CATEGORY", MENU_GROUP.fetchFrom(params));
       
   842         data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
       
   843         data.put("APPLICATION_COPYRIGHT", COPYRIGHT.fetchFrom(params));
   355         data.put("APPLICATION_COPYRIGHT", COPYRIGHT.fetchFrom(params));
   844         data.put("APPLICATION_LICENSE_TEXT", LICENSE_TEXT.fetchFrom(params));
   356         data.put("APPLICATION_LICENSE_TEXT", LICENSE_TEXT.fetchFrom(params));
   845         data.put("APPLICATION_ARCH", getDebArch());
   357         data.put("APPLICATION_ARCH", getDebArch());
   846         data.put("APPLICATION_INSTALLED_SIZE",
   358         data.put("APPLICATION_INSTALLED_SIZE", Long.toString(
   847                 Long.toString(getInstalledSizeKB(params)));
   359                 createMetaPackage(params).sourceApplicationLayout().sizeInBytes() >> 10));
   848         data.put("PACKAGE_DEPENDENCIES", LINUX_PACKAGE_DEPENDENCIES.fetchFrom(
       
   849                 params));
       
   850         data.put("RUNTIME_INSTALLER", "" +
       
   851                 StandardBundlerParam.isRuntimeInstaller(params));
       
   852 
   360 
   853         return data;
   361         return data;
   854     }
   362     }
   855 
   363 
   856     private File getConfig_DesktopShortcutFile(File rootDir,
       
   857             Map<String, ? super Object> params) {
       
   858         return new File(rootDir, APP_NAME.fetchFrom(params) + ".desktop");
       
   859     }
       
   860 
       
   861     private File getConfig_IconFile(File rootDir,
       
   862             Map<String, ? super Object> params) {
       
   863         return new File(rootDir, APP_NAME.fetchFrom(params) + ".png");
       
   864     }
       
   865 
       
   866     private File getConfig_ControlFile(Map<String, ? super Object> params) {
       
   867         return new File(CONFIG_DIR.fetchFrom(params), "control");
       
   868     }
       
   869 
       
   870     private File getConfig_PreinstallFile(Map<String, ? super Object> params) {
       
   871         return new File(CONFIG_DIR.fetchFrom(params), "preinst");
       
   872     }
       
   873 
       
   874     private File getConfig_PrermFile(Map<String, ? super Object> params) {
       
   875         return new File(CONFIG_DIR.fetchFrom(params), "prerm");
       
   876     }
       
   877 
       
   878     private File getConfig_PostinstallFile(Map<String, ? super Object> params) {
       
   879         return new File(CONFIG_DIR.fetchFrom(params), "postinst");
       
   880     }
       
   881 
       
   882     private File getConfig_PostrmFile(Map<String, ? super Object> params) {
       
   883         return new File(CONFIG_DIR.fetchFrom(params), "postrm");
       
   884     }
       
   885 
       
   886     private File getConfig_CopyrightFile(Map<String, ? super Object> params) {
   364     private File getConfig_CopyrightFile(Map<String, ? super Object> params) {
   887         return Path.of(DEB_IMAGE_DIR.fetchFrom(params).getAbsolutePath(), "usr",
   365         PlatformPackage thePackage = createMetaPackage(params);
   888                 "share", "doc", BUNDLE_NAME.fetchFrom(params), "copyright").toFile();
   366         return thePackage.sourceRoot().resolve(Path.of("usr/share/doc",
   889     }
   367                 thePackage.name(), "copyright")).toFile();
   890 
       
   891     private File getConfig_RootDirectory(
       
   892             Map<String, ? super Object> params) {
       
   893         return Path.of(APP_IMAGE_ROOT.fetchFrom(params).getAbsolutePath(),
       
   894                 BUNDLE_NAME.fetchFrom(params)).toFile();
       
   895     }
   368     }
   896 
   369 
   897     private File buildDeb(Map<String, ? super Object> params,
   370     private File buildDeb(Map<String, ? super Object> params,
   898             File outdir) throws IOException {
   371             File outdir) throws IOException {
   899         File outFile = new File(outdir,
   372         File outFile = new File(outdir,
   900                 FULL_PACKAGE_NAME.fetchFrom(params)+".deb");
   373                 FULL_PACKAGE_NAME.fetchFrom(params)+".deb");
   901         Log.verbose(MessageFormat.format(I18N.getString(
   374         Log.verbose(MessageFormat.format(I18N.getString(
   902                 "message.outputting-to-location"), outFile.getAbsolutePath()));
   375                 "message.outputting-to-location"), outFile.getAbsolutePath()));
   903 
   376 
   904         outFile.getParentFile().mkdirs();
   377         PlatformPackage thePackage = createMetaPackage(params);
   905 
   378 
   906         // run dpkg
   379         // run dpkg
   907         ProcessBuilder pb = new ProcessBuilder(
   380         ProcessBuilder pb = new ProcessBuilder(
   908                 "fakeroot", TOOL_DPKG_DEB, "-b",
   381                 "fakeroot", TOOL_DPKG_DEB, "-b",
   909                 FULL_PACKAGE_NAME.fetchFrom(params),
   382                 thePackage.sourceRoot().toString(),
   910                 outFile.getAbsolutePath());
   383                 outFile.getAbsolutePath());
   911         pb = pb.directory(DEB_IMAGE_DIR.fetchFrom(params).getParentFile());
       
   912         IOUtils.exec(pb);
   384         IOUtils.exec(pb);
   913 
   385 
   914         Log.verbose(MessageFormat.format(I18N.getString(
   386         Log.verbose(MessageFormat.format(I18N.getString(
   915                 "message.output-to-location"), outFile.getAbsolutePath()));
   387                 "message.output-to-location"), outFile.getAbsolutePath()));
   916 
   388 
   926     public String getID() {
   398     public String getID() {
   927         return "deb";
   399         return "deb";
   928     }
   400     }
   929 
   401 
   930     @Override
   402     @Override
   931     public String getBundleType() {
       
   932         return "INSTALLER";
       
   933     }
       
   934 
       
   935     @Override
       
   936     public File execute(Map<String, ? super Object> params,
       
   937             File outputParentDir) throws PackagerException {
       
   938         return bundle(params, outputParentDir);
       
   939     }
       
   940 
       
   941     @Override
       
   942     public boolean supported(boolean runtimeInstaller) {
   403     public boolean supported(boolean runtimeInstaller) {
   943         return isSupported();
       
   944     }
       
   945 
       
   946     public static boolean isSupported() {
       
   947         if (Platform.getPlatform() == Platform.LINUX) {
   404         if (Platform.getPlatform() == Platform.LINUX) {
   948             if (testTool(TOOL_DPKG_DEB, "1")) {
   405             if (testTool(TOOL_DPKG_DEB, "1")) {
   949                 return true;
   406                 return true;
   950             }
   407             }
   951         }
   408         }
   952         return false;
   409         return false;
   953     }
   410     }
   954 
   411 
   955     public int getSquareSizeOfImage(File f) {
       
   956         try {
       
   957             BufferedImage bi = ImageIO.read(f);
       
   958             if (bi.getWidth() == bi.getHeight()) {
       
   959                 return bi.getWidth();
       
   960             } else {
       
   961                 return 0;
       
   962             }
       
   963         } catch (Exception e) {
       
   964             Log.verbose(e);
       
   965             return 0;
       
   966         }
       
   967     }
       
   968 
       
   969     @Override
   412     @Override
   970     public boolean isDefault() {
   413     public boolean isDefault() {
   971         return isDebian();
   414         return isDebian();
   972     }
   415     }
   973 
   416