1 /* 2 * Copyright (c) 2012, 2014, 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 com.sun.javafx.tools.packager.bundlers; 27 28 import com.oracle.bundlers.BundlerParamInfo; 29 import com.oracle.bundlers.StandardBundlerParam; 30 import com.sun.javafx.tools.packager.Log; 31 import com.sun.javafx.tools.packager.PackagerLib; 32 33 import java.io.File; 34 import java.io.IOException; 35 import java.util.*; 36 import java.util.jar.Attributes; 37 import java.util.jar.JarFile; 38 import java.util.jar.Manifest; 39 40 public class BundleParams { 41 42 final protected Map<String, ? super Object> params; 43 44 public static final String PARAM_RUNTIME = "runtime"; // RelativeFileSet //KEY 45 public static final String PARAM_APP_RESOURCES = "appResources"; // RelativeFileSet //KEY 46 public static final String PARAM_TYPE = "type"; // BundlerType 47 public static final String PARAM_BUNDLE_FORMAT = "bundleFormat"; // String 48 public static final String PARAM_ICON = "icon"; // String //KEY 49 50 /* Name of bundle file and native launcher. 51 Also used as CFBundleName on Mac */ 52 public static final String PARAM_APP_NAME = "appName"; // String //KEY 53 public static final String PARAM_NAME = "name"; // String //KEY 54 55 /* application vendor, used by most of the bundlers */ 56 public static final String PARAM_VENDOR = "vendor"; // String //KEY 57 58 /* email name and email, only used for debian */ 59 public static final String PARAM_EMAIL = "email"; // String //KEY 60 61 /* Copyright. Used on Mac */ 62 public static final String PARAM_COPYRIGHT = "copyright"; // String //KEY 63 64 /* GUID on windows for MSI, CFBundleIdentifier on Mac 65 If not compatible with requirements then bundler either do not bundle 66 or autogenerate */ 67 public static final String PARAM_IDENTIFIER = "identifier"; // String //KEY 68 69 /* shortcut preferences */ 70 public static final String PARAM_SHORTCUT = "shortcutHint"; // boolean //KEY 71 public static final String PARAM_MENU = "menuHint"; // boolean //KEY 72 73 /* Application version. Format may differ for different bundlers */ 74 public static final String PARAM_VERSION = "appVersion"; // String //KEY 75 /* Application category. Used at least on Mac/Linux. Value is platform specific */ 76 public static final String PARAM_CATEGORY = "applicationCategory"; // String //KEY 77 78 /* Optional short application */ 79 public static final String PARAM_TITLE = "title"; // String //KEY 80 81 /* Optional application description. Used by MSI and on Linux */ 82 public static final String PARAM_DESCRIPTION = "description"; // String //KEY 83 84 /* License type. Needed on Linux (rpm) */ 85 public static final String PARAM_LICENSE_TYPE = "licenseType"; // String //KEY 86 87 /* File(s) with license. Format is OS/bundler specific */ 88 public static final String PARAM_LICENSE_FILES = "licenseFiles"; // List<String> //KEY 89 90 /* user or system level install. 91 null means "default" */ 92 public static final String PARAM_SYSTEM_WIDE = "systemWide"; // Boolean //KEY 93 94 /* Main application class. Not used directly but used to derive default values */ 95 public static final String PARAM_APPLICATION_CLASS = "applicationClass"; // String //KEY 96 97 //list of jvm args (in theory string can contain spaces and need to be escaped 98 private List<String> jvmargs = new LinkedList<>(); 99 //list of jvm args (in theory string can contain spaces and need to be escaped 100 private Map<String, String> jvmUserArgs = new HashMap<>(); 101 102 //list of jvm properties (can also be passed as VM args 103 private Map<String, String> jvmProperties = new HashMap<>(); 104 105 /** 106 * create a new bundle with all default values 107 */ 108 public BundleParams() { 109 params = new HashMap<>(); 110 } 111 112 /** 113 * Create a bundle params with a copy of the params 114 * @param params map of initial parameters to be copied in. 115 */ 116 public BundleParams(Map<String, ?> params) { 117 this.params = new HashMap<>(params); 118 } 119 120 public void addAllBundleParams(Map<String, ? super Object> p) { 121 params.putAll(p); 122 } 123 124 public <C> C fetchParam(BundlerParamInfo<C> paramInfo) { 125 return paramInfo.fetchFrom(params); 126 } 127 128 @SuppressWarnings("unchecked") 129 public <C> C fetchParamWithDefault(Class<C> klass, C defaultValue, String... keys) { 130 for (String key : keys) { 131 Object o = params.get(key); 132 if (klass.isInstance(o)) { 133 return (C) o; 134 } else if (params.containsKey(keys) && o == null) { 135 return null; 136 // } else if (o != null) { 137 // TODO log an error. 138 } 139 } 140 return defaultValue; 141 } 142 143 public <C> C fetchParam(Class<C> klass, String... keys) { 144 return fetchParamWithDefault(klass, null, keys); 145 } 146 147 //NOTE: we do not care about application parameters here 148 // as they will be embeded into jar file manifest and 149 // java launcher will take care of them! 150 151 public Map<String, ? super Object> getBundleParamsAsMap() { 152 return new HashMap<String, Object>(params); 153 } 154 155 public void setJvmargs(List<String> jvmargs) { 156 this.jvmargs = jvmargs; 157 } 158 159 public void setJvmUserArgs(Map<String, String> userArgs) { 160 this.jvmUserArgs = userArgs; 161 } 162 163 public void setJvmProperties(Map<String, String> jvmProperties) { 164 this.jvmProperties = jvmProperties; 165 } 166 167 public List<String> getAllJvmOptions() { 168 List<String> all = new LinkedList<>(); 169 all.addAll(jvmargs); 170 for(String k: jvmProperties.keySet()) { 171 all.add("-D"+k+"="+jvmProperties.get(k)); //TODO: We are not escaping values here... 172 } 173 return all; 174 } 175 176 public Map<String, String> getAllJvmUserOptions() { 177 Map<String, String> all = new HashMap<>(); 178 all.putAll(jvmUserArgs); 179 return all; 180 } 181 182 public String getApplicationID() { 183 return fetchParam(StandardBundlerParam.IDENTIFIER); 184 } 185 186 public String getPreferencesID() { 187 return fetchParam(StandardBundlerParam.PREFERENCES_ID); 188 } 189 190 public String getTitle() { 191 return fetchParam(StandardBundlerParam.TITLE); //FIXME title 192 } 193 194 public void setTitle(String title) { 195 putUnlessNull(PARAM_TITLE, title); 196 } 197 198 public String getApplicationClass() { 199 return fetchParam(StandardBundlerParam.MAIN_CLASS); 200 } 201 202 public void setApplicationClass(String applicationClass) { 203 putUnlessNull(PARAM_APPLICATION_CLASS, applicationClass); 204 } 205 206 public String getAppVersion() { 207 return fetchParam(StandardBundlerParam.VERSION); 208 } 209 210 public void setAppVersion(String version) { 211 putUnlessNull(PARAM_VERSION, version); 212 } 213 214 public String getDescription() { 215 return fetchParam(StandardBundlerParam.NAME); //FIXME DESCRIPTION); 216 } 217 218 public void setDescription(String s) { 219 putUnlessNull(PARAM_DESCRIPTION, s); 220 } 221 222 public String getLicenseType() { 223 return fetchParam(StandardBundlerParam.LICENSE_TYPE); //FIXME 224 } 225 226 public void setLicenseType(String version) { 227 putUnlessNull(PARAM_LICENSE_TYPE, version); 228 } 229 230 //path is relative to the application root 231 public void addLicenseFile(String path) { 232 @SuppressWarnings("unchecked") 233 List<String> licenseFile = fetchParam(List.class, PARAM_LICENSE_FILES); 234 if (licenseFile == null) { 235 licenseFile = new ArrayList<>(); 236 params.put(PARAM_LICENSE_FILES, licenseFile); 237 } 238 licenseFile.add(path); 239 } 240 241 public Boolean getSystemWide() { 242 return fetchParam(StandardBundlerParam.SYSTEM_WIDE); 243 } 244 245 public void setSystemWide(Boolean b) { 246 putUnlessNull(PARAM_SYSTEM_WIDE, b); 247 } 248 249 public RelativeFileSet getRuntime() { 250 return fetchParam(StandardBundlerParam.RUNTIME); 251 } 252 253 public boolean isShortcutHint() { 254 return fetchParam(StandardBundlerParam.SHORTCUT_HINT); 255 } 256 257 public void setShortcutHint(boolean v) { 258 putUnlessNull(PARAM_SHORTCUT, v); 259 } 260 261 public boolean isMenuHint() { 262 return fetchParam(StandardBundlerParam.MENU_HINT); 263 } 264 265 public void setMenuHint(boolean v) { 266 putUnlessNull(PARAM_MENU, v); 267 } 268 269 public String getName() { 270 return fetchParam(StandardBundlerParam.NAME); 271 } 272 273 public void setName(String name) { 274 putUnlessNull(PARAM_NAME, name); 275 } 276 277 public BundleType getType() { 278 return fetchParam(BundleType.class, PARAM_TYPE); 279 } 280 281 public void setType(BundleType type) { 282 putUnlessNull(PARAM_TYPE, type); 283 } 284 285 public String getBundleFormat() { 286 return fetchParam(String.class, PARAM_BUNDLE_FORMAT); 287 } 288 289 public void setBundleFormat(String t) { 290 putUnlessNull(PARAM_BUNDLE_FORMAT, t); 291 } 292 293 public static boolean shouldExclude(File baseDir, File f, Rule ruleset[]) { 294 if (ruleset == null) { 295 return false; 296 } 297 298 String fname = f.getAbsolutePath().toLowerCase().substring( 299 baseDir.getAbsolutePath().length()); 300 //first rule match defines the answer 301 for (Rule r: ruleset) { 302 if (r.match(fname)) { 303 return !r.treatAsAccept(); 304 } 305 } 306 //default is include 307 return false; 308 } 309 310 public static void walk(File base, File root, Rule ruleset[], Set<File> files) { 311 if (!root.isDirectory()) { 312 if (root.isFile()) { 313 files.add(root); 314 } 315 return; 316 } 317 318 File[] lst = root.listFiles(); 319 if (lst != null) { 320 for (File f : lst) { 321 //ignore symbolic links! 322 if (IOUtils.isNotSymbolicLink(f) && !shouldExclude(base, f, ruleset)) { 323 if (f.isDirectory()) { 324 walk(base, f, ruleset, files); 325 } else if (f.isFile()) { 326 //add to list 327 files.add(f); 328 } 329 } 330 } 331 } 332 } 333 334 335 @SuppressWarnings("unchecked") 336 public List<String> getLicenseFile() { 337 return fetchParam(List.class, PARAM_LICENSE_FILES); 338 } 339 340 public List<String> getJvmargs() { 341 return jvmargs; 342 } 343 344 public static class Rule { 345 String regex; 346 boolean includeRule; 347 Type type; 348 enum Type {SUFFIX, PREFIX, SUBSTR, REGEX} 349 350 private Rule(String regex, boolean includeRule, Type type) { 351 this.regex = regex; 352 this.type = type; 353 this.includeRule = includeRule; 354 } 355 356 boolean match(String str) { 357 if (type == Type.SUFFIX) { 358 return str.endsWith(regex); 359 } 360 if (type == Type.PREFIX) { 361 return str.startsWith(regex); 362 } 363 if (type == Type.SUBSTR) { 364 return str.contains(regex); 365 } 366 return str.matches(regex); 367 } 368 369 boolean treatAsAccept() {return includeRule;} 370 371 static Rule suffix(String s) { 372 return new Rule(s, true, Type.SUFFIX); 373 } 374 static Rule suffixNeg(String s) { 375 return new Rule(s, false, Type.SUFFIX); 376 } 377 static Rule prefix(String s) { 378 return new Rule(s, true, Type.PREFIX); 379 } 380 static Rule prefixNeg(String s) { 381 return new Rule(s, false, Type.PREFIX); 382 } 383 static Rule substr(String s) { 384 return new Rule(s, true, Type.SUBSTR); 385 } 386 static Rule substrNeg(String s) { 387 return new Rule(s, false, Type.SUBSTR); 388 } 389 } 390 391 //Subsetting of JRE is restricted. 392 //JRE README defines what is allowed to strip: 393 // http://www.oracle.com/technetwork/java/javase/jre-7-readme-430162.html 394 // 395 //In addition to this we may need to keep deploy jars and deploy.dll 396 // because JavaFX apps might need JNLP services 397 //Also, embedded launcher uses deploy.jar to access registry 398 // (although this is not needed) 399 public static Rule macRules[] = { 400 Rule.suffixNeg("macos/libjli.dylib"), 401 Rule.suffixNeg("resources"), 402 Rule.suffixNeg("home/bin"), 403 Rule.suffixNeg("home/db"), 404 Rule.suffixNeg("home/demo"), 405 Rule.suffixNeg("home/include"), 406 Rule.suffixNeg("home/lib"), 407 Rule.suffixNeg("home/man"), 408 Rule.suffixNeg("home/release"), 409 Rule.suffixNeg("home/sample"), 410 Rule.suffixNeg("home/src.zip"), 411 //"home/rt" is not part of the official builds 412 // but we may be creating this symlink to make older NB projects 413 // happy. Make sure to not include it into final artifact 414 Rule.suffixNeg("home/rt"), 415 Rule.suffixNeg("jre/bin"), 416 Rule.suffixNeg("jre/bin/rmiregistry"), 417 Rule.suffixNeg("jre/bin/tnameserv"), 418 Rule.suffixNeg("jre/bin/keytool"), 419 Rule.suffixNeg("jre/bin/klist"), 420 Rule.suffixNeg("jre/bin/ktab"), 421 Rule.suffixNeg("jre/bin/policytool"), 422 Rule.suffixNeg("jre/bin/orbd"), 423 Rule.suffixNeg("jre/bin/servertool"), 424 Rule.suffixNeg("jre/bin/javaws"), 425 Rule.suffixNeg("jre/bin/java"), 426 // Rule.suffixNeg("jre/lib/ext"), //need some of jars there for https to work 427 Rule.suffixNeg("jre/lib/nibs"), 428 //keep core deploy APIs but strip plugin dll 429 // Rule.suffixNeg("jre/lib/deploy"), 430 // Rule.suffixNeg("jre/lib/deploy.jar"), 431 // Rule.suffixNeg("jre/lib/javaws.jar"), 432 // Rule.suffixNeg("jre/lib/libdeploy.dylib"), 433 // Rule.suffixNeg("jre/lib/plugin.jar"), 434 Rule.suffixNeg("jre/lib/libnpjp2.dylib"), 435 Rule.suffixNeg("jre/lib/security/javaws.policy") 436 }; 437 438 public static Rule[] winRules = { 439 Rule.prefixNeg("\\bin\\new_plugin"), 440 Rule.suffix("deploy.jar"), //take deploy.jar 441 Rule.prefixNeg("\\lib\\deploy"), 442 Rule.suffixNeg(".pdb"), 443 Rule.suffixNeg(".map"), 444 Rule.suffixNeg("axbridge.dll"), 445 Rule.suffixNeg("eula.dll"), 446 Rule.substrNeg("javacpl"), 447 Rule.suffixNeg("wsdetect.dll"), 448 Rule.substrNeg("eployjava1.dll"), //NP and IE versions 449 Rule.substrNeg("bin\\jp2"), 450 Rule.substrNeg("bin\\jpi"), 451 // Rule.suffixNeg("lib\\ext"), //need some of jars there for https to work 452 Rule.suffixNeg("ssv.dll"), 453 Rule.substrNeg("npjpi"), 454 Rule.substrNeg("npoji"), 455 Rule.suffixNeg(".exe"), 456 //keep core deploy files as JavaFX APIs use them 457 // Rule.suffixNeg("deploy.dll"), 458 // Rule.suffixNeg("deploy.jar"), 459 // Rule.suffixNeg("javaws.jar"), 460 // Rule.suffixNeg("plugin.jar"), 461 Rule.suffix(".jar") 462 }; 463 464 public static Rule[] linuxRules = { 465 Rule.prefixNeg("/bin"), 466 Rule.prefixNeg("/plugin"), 467 // Rule.prefixNeg("/lib/ext"), //need some of jars there for https to work 468 Rule.suffix("deploy.jar"), //take deploy.jar 469 Rule.prefixNeg("/lib/deploy"), 470 Rule.prefixNeg("/lib/desktop"), 471 Rule.substrNeg("libnpjp2.so") 472 }; 473 474 //Validation approach: 475 // - JRE marker (rt.jar) 476 // - FX marker (jfxrt.jar) 477 // - JDK marker (tools.jar) 478 private static boolean checkJDKRoot(File jdkRoot) { 479 File rtJar = new File(jdkRoot, "jre/lib/rt.jar"); 480 if (!rtJar.exists()) { 481 Log.verbose("rt.jar is not found at " + rtJar.getAbsolutePath()); 482 return false; 483 } 484 485 File jfxJar = new File(jdkRoot, "jre/lib/ext/jfxrt.jar"); 486 if (!jfxJar.exists()) { 487 //Try again with new location 488 jfxJar = new File(jdkRoot, "jre/lib/jfxrt.jar"); 489 if (!jfxJar.exists()) { 490 Log.verbose("jfxrt.jar is not found at " + jfxJar.getAbsolutePath()); 491 return false; 492 } 493 } 494 495 496 File toolsJar = new File(jdkRoot, "lib/tools.jar"); 497 if (!toolsJar.exists()) { 498 Log.verbose("tools.jar is not found at " + toolsJar.getAbsolutePath()); 499 return false; 500 } 501 502 return true; 503 } 504 505 //Depending on platform and user input we may get different "references" 506 //Should support 507 // - java.home 508 // - reference to JDK install folder 509 // - should NOT support JRE dir 510 //Note: input could be null (then we asked to use system JRE) 511 // or it must be valid directory 512 //Returns null on validation failure. Returns jre root if ok. 513 static File validateRuntimeLocation(File javaHome) { 514 if (javaHome == null) { 515 return null; 516 } 517 File jdkRoot; 518 519 boolean isMac = System.getProperty("os.name").toLowerCase().contains("os x"); 520 521 File rtJar = new File(javaHome, "lib/rt.jar"); 522 if (rtJar.exists()) { //must be "java.home" case 523 //i.e. we are in JRE folder 524 jdkRoot = javaHome.getParentFile(); 525 } else { //expect it to be root of JDK installation folder 526 //On Mac it could be jdk/ or jdk/Contents/Home 527 //Norm to jdk/Contents/Home for validation 528 if (isMac) { 529 File f = new File(javaHome, "Contents/Home"); 530 if (f.exists() && f.isDirectory()) { 531 javaHome = f; 532 } 533 } 534 jdkRoot = javaHome; 535 } 536 537 if (!checkJDKRoot(jdkRoot)) { 538 throw new RuntimeException( 539 "Can not find JDK artifacts in specified location: " 540 + javaHome.getAbsolutePath()); 541 } 542 543 return new File(jdkRoot, "jre"); 544 } 545 546 //select subset of given runtime using predefined rules 547 public void setRuntime(File baseDir) { 548 baseDir = validateRuntimeLocation(baseDir); 549 550 //mistake or explicit intent to use system runtime 551 if (baseDir == null) { 552 Log.verbose("No Java runtime to embed. Package will need system Java."); 553 params.put(PARAM_RUNTIME, null); 554 return; 555 } 556 doSetRuntime(baseDir); 557 } 558 559 public void setDefaultRuntime() { 560 File f = new File(System.getProperty("java.home")); 561 doSetRuntime(f); 562 } 563 564 //input dir "jdk/jre" (i.e. jre folder in the jdk) 565 private void doSetRuntime(File baseDir) { 566 boolean isMac = System.getProperty("os.name").toLowerCase().contains("os x"); 567 568 //Normalization: on MacOS we need to point to the top of JDK dir 569 // (other platforms are fine) 570 if (isMac) { 571 //On Mac we need Bundle root, not jdk/Contents/Home 572 baseDir = baseDir.getParentFile().getParentFile().getParentFile(); 573 } 574 575 Set<File> lst = new HashSet<>(); 576 577 Rule ruleset[]; 578 if (System.getProperty("os.name").startsWith("Mac")) { 579 ruleset = macRules; 580 } else if (System.getProperty("os.name").startsWith("Win")) { 581 ruleset = winRules; 582 } else { 583 //must be linux 584 ruleset = linuxRules; 585 } 586 587 walk(baseDir, baseDir, ruleset, lst); 588 589 params.put(PARAM_RUNTIME, new RelativeFileSet(baseDir, lst)); 590 } 591 592 //Currently unused? 593 // 594 //public void setRuntime(RelativeFileSet fs) { 595 // runtime = fs; 596 //} 597 598 public RelativeFileSet getAppResource() { 599 return fetchParam(StandardBundlerParam.APP_RESOURCES); 600 } 601 602 public void setAppResource(RelativeFileSet fs) { 603 putUnlessNull(PARAM_APP_RESOURCES, fs); 604 } 605 606 public File getIcon() { 607 return fetchParam(StandardBundlerParam.ICON); 608 } 609 610 public void setIcon(File icon) { 611 putUnlessNull(PARAM_ICON, icon); 612 } 613 614 public String getApplicationCategory() { 615 return fetchParam(String.class, PARAM_CATEGORY); //FIXME 616 } 617 618 public void setApplicationCategory(String category) { 619 putUnlessNull(PARAM_CATEGORY, category); 620 } 621 622 public String getMainClassName() { 623 String applicationClass = getApplicationClass(); 624 625 if (applicationClass == null) { 626 return null; 627 } 628 629 int idx = applicationClass.lastIndexOf("."); 630 if (idx >= 0) { 631 return applicationClass.substring(idx+1); 632 } 633 return applicationClass; 634 } 635 636 public String getCopyright() { 637 return fetchParam(StandardBundlerParam.COPYRIGHT); 638 } 639 640 public void setCopyright(String c) { 641 putUnlessNull(PARAM_COPYRIGHT, c); 642 } 643 644 public String getIdentifier() { 645 return fetchParam(StandardBundlerParam.IDENTIFIER); 646 } 647 648 public void setIdentifier(String s) { 649 putUnlessNull(PARAM_IDENTIFIER, s); 650 } 651 652 private String mainJar = null; 653 private String mainJarClassPath = null; 654 private boolean useFXPackaging = true; 655 656 //are we packaging JavaFX application or regular executable Jar? 657 public boolean useJavaFXPackaging() { 658 if (mainJar == null) { 659 //this will find out answer 660 getMainApplicationJar(); 661 } 662 return useFXPackaging; 663 } 664 665 //For regular executable Jars we need to take care of classpath 666 //For JavaFX executable jars we do not need to pay attention to ClassPath entry in manifest 667 public String getAppClassPath() { 668 if (mainJar == null) { 669 //this will find out answer 670 getMainApplicationJar(); 671 } 672 if (useFXPackaging || mainJarClassPath == null) { 673 return ""; 674 } 675 return mainJarClassPath; 676 } 677 678 //assuming that application was packaged according to the rules 679 // we must have application jar, i.e. jar where we embed launcher 680 // and have main application class listed as main class! 681 //If there are more than one, or none - it will be treated as deployment error 682 // 683 //Note we look for both JavaFX executable jars and regular executable jars 684 //As long as main "application" entry point is the same it is main class 685 // (i.e. for FX jar we will use JavaFX manifest entry ...) 686 public String getMainApplicationJar() { 687 if (mainJar != null) { 688 return mainJar; 689 } 690 691 RelativeFileSet appResources = getAppResource(); 692 String applicationClass = getApplicationClass(); 693 694 if (appResources == null || applicationClass == null) { 695 return null; 696 } 697 File srcdir = appResources.getBaseDirectory(); 698 for (String fname : appResources.getIncludedFiles()) { 699 JarFile jf; 700 try { 701 jf = new JarFile(new File(srcdir, fname)); 702 Manifest m = jf.getManifest(); 703 Attributes attrs = (m != null) ? m.getMainAttributes() : null; 704 if (attrs != null) { 705 boolean javaMain = applicationClass.equals( 706 attrs.getValue(Attributes.Name.MAIN_CLASS)); 707 boolean fxMain = applicationClass.equals( 708 attrs.getValue(PackagerLib.MANIFEST_JAVAFX_MAIN)); 709 if (javaMain || fxMain) { 710 useFXPackaging = fxMain; 711 mainJar = fname; 712 mainJarClassPath = attrs.getValue(Attributes.Name.CLASS_PATH); 713 return mainJar; 714 } 715 } 716 } catch (IOException ignore) { 717 } 718 } 719 return null; 720 } 721 722 public String getVendor() { 723 return fetchParam(StandardBundlerParam.VENDOR); 724 } 725 726 public void setVendor(String vendor) { 727 putUnlessNull(PARAM_VENDOR, vendor); 728 } 729 730 public String getEmail() { 731 return fetchParam(String.class, PARAM_EMAIL); 732 } 733 734 public void setEmail(String email) { 735 putUnlessNull(PARAM_EMAIL, email); 736 } 737 738 public void putUnlessNull(String param, Object value) { 739 if (value != null) { 740 params.put(param, value); 741 } 742 } 743 744 }