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> p) 222 throws UnsupportedPlatformException, ConfigException { 223 try { 224 if (p == 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(p).validate(p); 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(p); 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(p); 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); 254 if (mimes == null || mimes.isEmpty()) { 255 String msgKey = 256 "error.no-content-types-for-file-association"; 257 throw new ConfigException( 258 MessageFormat.format(I18N.getString(msgKey), i), 259 I18N.getString(msgKey + ".advise")); 260 261 } else if (mimes.size() > 1) { 262 String msgKey = 263 "error.too-many-content-types-for-file-association"; 264 throw new ConfigException( 265 MessageFormat.format(I18N.getString(msgKey), i), 266 I18N.getString(msgKey + ".advise")); 267 } 268 } 269 } 270 271 // bundle name has some restrictions 272 // the string converter will throw an exception if invalid 273 BUNDLE_NAME.getStringConverter().apply(BUNDLE_NAME.fetchFrom(p), p); 274 275 return true; 276 } catch (RuntimeException re) { 277 if (re.getCause() instanceof ConfigException) { 278 throw (ConfigException) re.getCause(); 279 } else { 280 throw new ConfigException(re); 281 } 282 } 283 } 284 285 private boolean prepareProto(Map<String, ? super Object> p) 286 throws PackagerException, IOException { 287 File appImage = StandardBundlerParam.getPredefinedAppImage(p); 288 File appDir = null; 289 290 // we either have an application image or need to build one 291 if (appImage != null) { 292 appDir = new File(APP_IMAGE_ROOT.fetchFrom(p), 293 APP_NAME.fetchFrom(p)); 294 // copy everything from appImage dir into appDir/name 295 IOUtils.copyRecursive(appImage.toPath(), appDir.toPath()); 296 } else { 297 appDir = APP_BUNDLER.fetchFrom(p).doBundle(p, 298 APP_IMAGE_ROOT.fetchFrom(p), true); 299 } 300 return appDir != null; 301 } 302 303 //@Override 304 public File bundle(Map<String, ? super Object> p, 305 File outdir) throws PackagerException { 306 if (!outdir.isDirectory() && !outdir.mkdirs()) { 307 throw new PackagerException ("error.cannot-create-output-dir", 308 outdir.getAbsolutePath()); 309 } 310 if (!outdir.canWrite()) { 311 throw new PackagerException("error.cannot-write-to-output-dir", 312 outdir.getAbsolutePath()); 313 } 314 315 // we want to create following structure 316 // <package-name> 317 // DEBIAN 318 // control (file with main package details) 319 // menu (request to create menu) 320 // ... other control files if needed .... 321 // opt (by default) 322 // AppFolder (this is where app image goes) 323 // launcher executable 324 // app 325 // runtime 326 327 File imageDir = DEB_IMAGE_DIR.fetchFrom(p); 328 File configDir = CONFIG_DIR.fetchFrom(p); 329 330 try { 331 332 imageDir.mkdirs(); 333 configDir.mkdirs(); 334 if (prepareProto(p) && prepareProjectConfig(p)) { 335 return buildDeb(p, outdir); 336 } 337 return null; 338 } catch (IOException ex) { 339 Log.verbose(ex); 340 throw new PackagerException(ex); 341 } 342 } 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 } | 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 UnsupportedPlatformException, 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); 254 if (mimes == null || mimes.isEmpty()) { 255 String msgKey = 256 "error.no-content-types-for-file-association"; 257 throw new ConfigException( 258 MessageFormat.format(I18N.getString(msgKey), i), 259 I18N.getString(msgKey + ".advise")); 260 261 } else if (mimes.size() > 1) { 262 String msgKey = 263 "error.too-many-content-types-for-file-association"; 264 throw new ConfigException( 265 MessageFormat.format(I18N.getString(msgKey), i), 266 I18N.getString(msgKey + ".advise")); 267 } 268 } 269 } 270 271 // bundle name has some restrictions 272 // the string converter will throw an exception if invalid 273 BUNDLE_NAME.getStringConverter().apply( 274 BUNDLE_NAME.fetchFrom(params), params); 275 276 return true; 277 } catch (RuntimeException re) { 278 if (re.getCause() instanceof ConfigException) { 279 throw (ConfigException) re.getCause(); 280 } else { 281 throw new ConfigException(re); 282 } 283 } 284 } 285 286 private boolean prepareProto(Map<String, ? super Object> params) 287 throws PackagerException, IOException { 288 File appImage = StandardBundlerParam.getPredefinedAppImage(params); 289 File appDir = null; 290 291 // we either have an application image or need to build one 292 if (appImage != null) { 293 appDir = new File(APP_IMAGE_ROOT.fetchFrom(params), 294 APP_NAME.fetchFrom(params)); 295 // copy everything from appImage dir into appDir/name 296 IOUtils.copyRecursive(appImage.toPath(), appDir.toPath()); 297 } else { 298 appDir = APP_BUNDLER.fetchFrom(params).doBundle(params, 299 APP_IMAGE_ROOT.fetchFrom(params), true); 300 } 301 return appDir != null; 302 } 303 304 //@Override 305 public File bundle(Map<String, ? super Object> params, 306 File outdir) throws PackagerException { 307 if (!outdir.isDirectory() && !outdir.mkdirs()) { 308 throw new PackagerException ("error.cannot-create-output-dir", 309 outdir.getAbsolutePath()); 310 } 311 if (!outdir.canWrite()) { 312 throw new PackagerException("error.cannot-write-to-output-dir", 313 outdir.getAbsolutePath()); 314 } 315 316 // we want to create following structure 317 // <package-name> 318 // DEBIAN 319 // control (file with main package details) 320 // menu (request to create menu) 321 // ... other control files if needed .... 322 // opt (by default) 323 // AppFolder (this is where app image goes) 324 // launcher executable 325 // app 326 // runtime 327 328 File imageDir = DEB_IMAGE_DIR.fetchFrom(params); 329 File configDir = CONFIG_DIR.fetchFrom(params); 330 331 try { 332 333 imageDir.mkdirs(); 334 configDir.mkdirs(); 335 if (prepareProto(params) && prepareProjectConfig(params)) { 336 return buildDeb(params, outdir); 337 } 338 return null; 339 } catch (IOException ex) { 340 Log.verbose(ex); 341 throw new PackagerException(ex); 342 } 343 } 344 345 /* 346 * set permissions with a string like "rwxr-xr-x" 347 * 348 * This cannot be directly backport to 22u which is built with 1.6 349 */ 350 private void setPermissions(File file, String permissions) { 351 Set<PosixFilePermission> filePermissions = 352 PosixFilePermissions.fromString(permissions); 353 try { 354 if (file.exists()) { 355 Files.setPosixFilePermissions(file.toPath(), filePermissions); 356 } |