1 /* 2 * Copyright (c) 2011, 2015, 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.ant; 27 28 import com.sun.javafx.tools.packager.CreateJarParams; 29 import com.sun.javafx.tools.packager.PackagerLib; 30 import java.io.File; 31 import java.util.Enumeration; 32 import java.util.HashMap; 33 import java.util.LinkedList; 34 import java.util.List; 35 import java.util.Map; 36 import org.apache.tools.ant.BuildException; 37 import org.apache.tools.ant.Task; 38 import org.apache.tools.ant.taskdefs.Manifest; 39 import org.apache.tools.ant.types.FileSet; 40 41 /** 42 * Package javafx application into jar file. The set of files to be included is 43 * defined by one or more nested fileset. Task also accepts jar Manifest to embed it into 44 * result jar file. 45 * <p> 46 * In addition to just creating jar archive it also: 47 * <ul> 48 * <li> embeds of JavaFX launcher (for double clickable jars) 49 * <li> embeds of fallback AWT applet (to be used if JavaFX is not available) 50 * <li> ensures jar manifests do not have "bad" entries (such as Class-Path) 51 * </ul> 52 * 53 * @ant.task name="jar" category="javafx" 54 */ 55 public class FXJar extends Task { 56 private String destFile = null; 57 private String codebase = null; 58 private Application app = null; 59 private Platform platform = null; 60 private Resources resources = null; 61 private List<FileSet> filesets = new LinkedList<FileSet>(); 62 private Manifest manifest = null; 63 64 private PackagerLib packager; 65 private CreateJarParams createJarParams; 66 67 private boolean css2bin = false; 68 69 private boolean verbose = false; 70 public void setVerbose(boolean v) { 71 verbose = v; 72 } 73 74 public Application createApplication() { 75 app = new Application(); 76 return app; 77 } 78 79 public Platform createPlatform() { 80 platform = new Platform(); 81 return platform; 82 } 83 84 private Permissions perms = null; 85 86 public Permissions createPermissions() { 87 perms = new Permissions(); 88 return perms; 89 } 90 91 public Resources createResources() { 92 resources = new Resources(); 93 return resources; 94 } 95 96 /** 97 * Location of output file. 98 * 99 * @ant.required 100 */ 101 public void setDestfile(String v) { 102 destFile = v; 103 } 104 105 /* 106 * If specified, then packager adds the "Codebase" attribute to the manifest file 107 * 108 * @ant.not-required Default is null. 109 */ 110 public void setCodebase(String v) { 111 codebase = v; 112 } 113 114 /** 115 * Enable converting CSS files to binary format for faster parsing at 116 * runtime. 117 * 118 * @ant.not-required Default is false. 119 */ 120 public void setCss2Bin(boolean v) { 121 css2bin = v; 122 } 123 124 public FXJar() { 125 packager = new PackagerLib(); 126 createJarParams = new CreateJarParams(); 127 } 128 129 130 @Override 131 public void execute() { 132 checkAttributesAndElements(); 133 134 createJarParams.setCss2bin(css2bin); 135 136 if (app != null) { 137 createJarParams.setApplicationClass(app.get().mainClass); 138 createJarParams.setPreloader(app.get().preloaderClass); 139 createJarParams.setFallback(app.get().fallbackApp); 140 createJarParams.setParams(app.get().parameters); 141 createJarParams.setArguments(app.get().getArguments()); 142 } 143 144 if (perms != null) { 145 createJarParams.setAllPermissions(perms.getElevated()); 146 } 147 148 if (codebase != null) { 149 createJarParams.setCodebase(codebase); 150 } 151 152 if (platform != null) { 153 createJarParams.setFxVersion(platform.get().javafx); 154 } 155 156 if (resources != null) { 157 createJarParams.setClasspath(resources.exportAsClassPath()); 158 } 159 160 final File f = new File(destFile); 161 createJarParams.setOutdir(f.isAbsolute() 162 ? null 163 : getProject().getBaseDir()); 164 createJarParams.setOutfile(destFile); 165 166 if (manifest != null) { 167 createJarParams.setManifestAttrs(getAttrSet(manifest)); 168 } 169 170 for (FileSet fileset: filesets) { 171 Utils.addResources(createJarParams, fileset); 172 } 173 174 try { 175 packager.packageAsJar(createJarParams); 176 } catch (Exception e) { 177 throw new BuildException(e.getMessage(), e); 178 } 179 } 180 181 public Manifest createManifest() { 182 manifest = new Manifest(); 183 return manifest; 184 } 185 186 public FileSet createFileSet() { 187 FileSet fileset = new FileSet(); 188 fileset.setProject(getProject()); 189 filesets.add(fileset); 190 return fileset; 191 } 192 193 private void checkAttributesAndElements() { 194 if (destFile == null) { 195 throw new BuildException("You must specify the destfile file to create."); 196 } 197 198 File f = new File(destFile); 199 if (!f.isAbsolute()) { 200 f = new File(getProject().getBaseDir(), destFile); 201 } 202 if (f.exists() && !f.isFile()) { 203 throw new BuildException(destFile + " is not a file."); 204 } 205 206 if (f.exists() && !f.canWrite()) { 207 throw new BuildException(destFile + " is read-only."); 208 } 209 210 if (filesets.isEmpty()) { 211 throw new BuildException("You must specify at least one fileset to be packed."); 212 } 213 214 boolean haveNonEmpty = false; 215 for (FileSet fileset: filesets) { 216 if (fileset.size() != 0) { 217 haveNonEmpty = true; 218 break; 219 } 220 } 221 222 if (!haveNonEmpty) { 223 throw new BuildException("All filesets are empty."); 224 } 225 226 if (app != null) { 227 app.selfcheck(); 228 } 229 } 230 231 private static Map<String, String> getAttrSet(Manifest manifest) { 232 Map<String, String> result = new HashMap<String, String>(); 233 234 Manifest.Section mainSection = manifest.getMainSection(); 235 for (Enumeration e = mainSection.getAttributeKeys(); e.hasMoreElements();) { 236 String attrKey = (String) e.nextElement(); 237 Manifest.Attribute attr = mainSection.getAttribute(attrKey); 238 result.put(attr.getName(), attr.getValue()); 239 } 240 return result; 241 } 242 }