1 /*
   2  * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.jpackage.internal;
  27 
  28 import java.io.File;
  29 import java.io.IOException;
  30 import java.net.MalformedURLException;
  31 import java.net.URL;
  32 import java.text.MessageFormat;
  33 import java.util.Arrays;
  34 import java.util.Collection;
  35 import java.util.Map;
  36 import java.util.ResourceBundle;
  37 
  38 import static jdk.jpackage.internal.StandardBundlerParam.*;
  39 
  40 public class LinuxAppBundler extends AbstractImageBundler {
  41 
  42     private static final ResourceBundle I18N = ResourceBundle.getBundle(
  43             "jdk.jpackage.internal.resources.LinuxResources");
  44 
  45     public static final BundlerParamInfo<File> ICON_PNG =
  46             new StandardBundlerParam<>(
  47             I18N.getString("param.icon-png.name"),
  48             I18N.getString("param.icon-png.description"),
  49             "icon.png",
  50             File.class,
  51             params -> {
  52                 File f = ICON.fetchFrom(params);
  53                 if (f != null && !f.getName().toLowerCase().endsWith(".png")) {
  54                     Log.error(MessageFormat.format(
  55                             I18N.getString("message.icon-not-png"), f));
  56                     return null;
  57                 }
  58                 return f;
  59             },
  60             (s, p) -> new File(s));
  61 
  62     public static final BundlerParamInfo<String> LINUX_INSTALL_DIR =
  63             new StandardBundlerParam<>(
  64             I18N.getString("param.linux-install-dir.name"),
  65             I18N.getString("param.linux-install-dir.description"),
  66             "linux-install-dir",
  67             String.class,
  68             params -> {
  69                  String dir = INSTALL_DIR.fetchFrom(params);
  70                  if (dir != null) {
  71                      if (dir.endsWith("/")) {
  72                          dir = dir.substring(0, dir.length()-1);
  73                      }
  74                      return dir;
  75                  }
  76                  return "/opt";
  77              },
  78             (s, p) -> s
  79     );
  80 
  81     public static final BundlerParamInfo<String> LINUX_PACKAGE_DEPENDENCIES =
  82             new StandardBundlerParam<>(
  83             I18N.getString("param.linux-package-dependencies.name"),
  84             I18N.getString("param.linux-package-dependencies.description"),
  85             Arguments.CLIOptions.LINUX_PACKAGE_DEPENDENCIES.getId(),
  86             String.class,
  87             params -> {
  88                  return "";
  89              },
  90             (s, p) -> s
  91     );
  92 
  93     @Override
  94     public boolean validate(Map<String, ? super Object> p)
  95             throws UnsupportedPlatformException, ConfigException {
  96         try {
  97             if (p == null) throw new ConfigException(
  98                     I18N.getString("error.parameters-null"),
  99                     I18N.getString("error.parameters-null.advice"));
 100 
 101             return doValidate(p);
 102         } catch (RuntimeException re) {
 103             if (re.getCause() instanceof ConfigException) {
 104                 throw (ConfigException) re.getCause();
 105             } else {
 106                 throw new ConfigException(re);
 107             }
 108         }
 109     }
 110 
 111     private boolean doValidate(Map<String, ? super Object> p)
 112             throws UnsupportedPlatformException, ConfigException {
 113         if (Platform.getPlatform() != Platform.LINUX) {
 114             throw new UnsupportedPlatformException();
 115         }
 116 
 117         imageBundleValidation(p);
 118 
 119         return true;
 120     }
 121 
 122     // it is static for the sake of sharing with "installer" bundlers
 123     // that may skip calls to validate/bundle in this class!
 124     public static File getRootDir(File outDir, Map<String, ? super Object> p) {
 125         return new File(outDir, APP_FS_NAME.fetchFrom(p));
 126     }
 127 
 128     public static String getLauncherCfgName(Map<String, ? super Object> p) {
 129         return "app/" + APP_FS_NAME.fetchFrom(p) +".cfg";
 130     }
 131 
 132     File doBundle(Map<String, ? super Object> p, File outputDirectory,
 133             boolean dependentTask) {
 134         if (Arguments.CREATE_JRE_INSTALLER.fetchFrom(p)) {
 135             return doJreBundle(p, outputDirectory, dependentTask);
 136         } else {
 137             return doAppBundle(p, outputDirectory, dependentTask);
 138         }
 139     }
 140 
 141     private File doJreBundle(Map<String, ? super Object> p,
 142             File outputDirectory, boolean dependentTask) {
 143         try {
 144             File rootDirectory = createRoot(p, outputDirectory, dependentTask,
 145                     APP_FS_NAME.fetchFrom(p), "linuxapp-image-builder");
 146             AbstractAppImageBuilder appBuilder = new LinuxAppImageBuilder(
 147                     APP_NAME.fetchFrom(p), outputDirectory.toPath());
 148             File predefined = PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
 149             if (predefined == null ) {
 150                 JLinkBundlerHelper.generateJre(p, appBuilder);
 151             } else {
 152                 return predefined;
 153             }
 154             return rootDirectory;
 155         } catch (Exception ex) {
 156             Log.error("Exception: "+ex);
 157             Log.debug(ex);
 158             return null;
 159         }
 160     }
 161 
 162     private File doAppBundle(Map<String, ? super Object> p,
 163             File outputDirectory, boolean dependentTask) {
 164         try {
 165             File rootDirectory = createRoot(p, outputDirectory, dependentTask,
 166                     APP_FS_NAME.fetchFrom(p), "linuxapp-image-builder");
 167             AbstractAppImageBuilder appBuilder = new LinuxAppImageBuilder(p,
 168                     outputDirectory.toPath());
 169             if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) {
 170                 JLinkBundlerHelper.execute(p, appBuilder);
 171             } else {
 172                 StandardBundlerParam.copyPredefinedRuntimeImage(p, appBuilder);
 173             }
 174             return rootDirectory;
 175         } catch (Exception ex) {
 176             Log.error("Exception: "+ex);
 177             Log.debug(ex);
 178             return null;
 179         }
 180     }
 181 
 182     @Override
 183     public String getName() {
 184         return I18N.getString("app.bundler.name");
 185     }
 186 
 187     @Override
 188     public String getDescription() {
 189         return I18N.getString("app.bundler.description");
 190     }
 191 
 192     @Override
 193     public String getID() {
 194         return "linux.app";
 195     }
 196 
 197     @Override
 198     public String getBundleType() {
 199         return "IMAGE";
 200     }
 201 
 202     @Override
 203     public Collection<BundlerParamInfo<?>> getBundleParameters() {
 204         return getAppBundleParameters();
 205     }
 206 
 207     public static Collection<BundlerParamInfo<?>> getAppBundleParameters() {
 208         return Arrays.asList(
 209                 APP_NAME,
 210                 APP_RESOURCES,
 211                 ARGUMENTS,
 212                 CLASSPATH,
 213                 JVM_OPTIONS,
 214                 MAIN_CLASS,
 215                 MAIN_JAR,
 216                 PREFERENCES_ID,
 217                 VERSION,
 218                 VERBOSE
 219         );
 220     }
 221 
 222     @Override
 223     public File execute(Map<String, ? super Object> params,
 224             File outputParentDir) {
 225         return doBundle(params, outputParentDir, false);
 226     }
 227 
 228     @Override
 229     public boolean supported() {
 230         return (Platform.getPlatform() == Platform.LINUX);
 231     }
 232 }