1 11 package org.eclipse.jdt.internal.ui.macbundler; 12 13 import java.io.*; 14 import java.util.*; 15 import java.util.List ; 16 17 import javax.xml.parsers.*; 18 import javax.xml.parsers.DocumentBuilder ; 19 import javax.xml.transform.*; 20 import javax.xml.transform.Transformer ; 21 import javax.xml.transform.dom.DOMSource ; 22 import javax.xml.transform.stream.StreamResult ; 23 24 import org.w3c.dom.*; 25 import org.w3c.dom.Document ; 26 27 import org.eclipse.core.runtime.IProgressMonitor; 28 29 30 public class BundleBuilder implements BundleAttributes { 31 32 private List fProcesses= new ArrayList(); 33 private BundleDescription fBundleDescription; 34 35 36 public void createBundle(BundleDescription bd, IProgressMonitor pm) throws IOException { 37 38 fBundleDescription= bd; 39 40 File tmp_dir= new File(bd.get(DESTINATIONDIRECTORY)); 41 String app_dir_name= bd.get(APPNAME) + ".app"; File app_dir= new File(tmp_dir, app_dir_name); 43 if (app_dir.exists()) 44 deleteDir(app_dir); 45 app_dir= createDir(tmp_dir, app_dir_name, false); 47 File contents_dir= createDir(app_dir, "Contents", false); createPkgInfo(contents_dir); 49 50 File macos_dir= createDir(contents_dir, "MacOS", false); String launcher_path= bd.get(LAUNCHER); 52 if (launcher_path == null) 53 throw new IOException(); 54 String launcher= copyFile(macos_dir, launcher_path, null); 55 56 File resources_dir= createDir(contents_dir, "Resources", false); File java_dir= createDir(resources_dir, "Java", false); 59 createInfoPList(contents_dir, resources_dir, java_dir, launcher); 60 61 Iterator iter= fProcesses.iterator(); 62 while (iter.hasNext()) { 63 Process p= (Process ) iter.next(); 64 try { 65 p.waitFor(); 66 } catch (InterruptedException e) { 67 } 69 } 70 } 71 72 private void createInfoPList(File contents_dir, File resources_dir, File java_dir, String launcher) throws IOException { 73 74 File info= new File(contents_dir, "Info.plist"); FileOutputStream fos= new FileOutputStream(info); 76 BufferedOutputStream fOutputStream= new BufferedOutputStream(fos); 77 78 DocumentBuilder docBuilder= null; 79 DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance(); 80 factory.setValidating(false); 81 try { 82 docBuilder= factory.newDocumentBuilder(); 83 } catch (ParserConfigurationException ex) { 84 System.err.println("createInfoPList: could not get XML builder"); } 86 Document doc= docBuilder.newDocument(); 87 88 Element plist= doc.createElement("plist"); doc.appendChild(plist); 90 plist.setAttribute("version", "1.0"); 92 Element dict= doc.createElement("dict"); plist.appendChild(dict); 94 95 pair(dict, "CFBundleExecutable", null, launcher); pair(dict, "CFBundleGetInfoString", GETINFO, null); pair(dict, "CFBundleInfoDictionaryVersion", null, "6.0"); 99 String iconName= null; 100 String appName= fBundleDescription.get(APPNAME, null); 101 if (appName != null) 102 iconName= appName + ".icns"; String fname= copyFile(resources_dir, fBundleDescription.get(ICONFILE, null), iconName); 104 if (fname != null) 105 pair(dict, "CFBundleIconFile", null, fname); 107 pair(dict, "CFBundleIdentifier", IDENTIFIER, null); pair(dict, "CFBundleName", APPNAME, null); pair(dict, "CFBundlePackageType", null, "APPL"); pair(dict, "CFBundleShortVersionString", VERSION, null); pair(dict, "CFBundleSignature", SIGNATURE, "????"); pair(dict, "CFBundleVersion", null, "1.0.1"); 114 Element jdict= doc.createElement("dict"); add(dict, "Java", jdict); 117 pair(jdict, "JVMVersion", JVMVERSION, null); pair(jdict, "MainClass", MAINCLASS, null); pair(jdict, "WorkingDirectory", WORKINGDIR, null); 121 if (fBundleDescription.get(USES_SWT, false)) 122 addTrue(jdict, "StartOnMainThread"); 124 String arguments= fBundleDescription.get(ARGUMENTS, null); 125 if (arguments != null) { 126 Element argArray= doc.createElement("array"); add(jdict, "Arguments", argArray); StringTokenizer st= new StringTokenizer(arguments); 129 while (st.hasMoreTokens()) { 130 String arg= st.nextToken(); 131 Element type= doc.createElement("string"); argArray.appendChild(type); 133 type.appendChild(doc.createTextNode(arg)); 134 } 135 } 136 137 pair(jdict, "VMOptions", VMOPTIONS, null); 139 int[] id= new int[] { 0 }; 140 ResourceInfo[] ris= fBundleDescription.getResources(true); 141 if (ris.length > 0) { 142 StringBuffer cp= new StringBuffer (); 143 for (int i= 0; i < ris.length; i++) { 144 ResourceInfo ri= ris[i]; 145 String e= processClasspathEntry(java_dir, ri.fPath, id); 146 if (cp.length() > 0) 147 cp.append(':'); 148 cp.append(e); 149 } 150 add(jdict, "ClassPath", cp.toString()); } 152 153 ris= fBundleDescription.getResources(false); 154 if (ris.length > 0) { 155 for (int i= 0; i < ris.length; i++) { 156 ResourceInfo ri= ris[i]; 157 processClasspathEntry(java_dir, ri.fPath, id); 158 } 159 } 160 161 try { 162 Transformer transformer= TransformerFactory.newInstance().newTransformer(); 164 transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//Apple Computer//DTD PLIST 1.0//EN"); transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://www.apple.com/DTDs/PropertyList-1.0.dtd"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); DOMSource source= new DOMSource (doc); 171 StreamResult result= new StreamResult (fOutputStream); 172 transformer.transform(source, result); 173 } catch (TransformerException e) { 174 System.err.println("createInfoPList: could not transform to XML"); } 176 } 177 178 private void add(Element dict, String key, Element value) { 179 Document document= dict.getOwnerDocument(); 180 Element k= document.createElement("key"); dict.appendChild(k); 182 k.appendChild(document.createTextNode(key)); 183 dict.appendChild(value); 184 } 185 186 private void create(Element parent, String s) { 187 Document document= parent.getOwnerDocument(); 188 Element type= document.createElement("string"); parent.appendChild(type); 190 type.appendChild(document.createTextNode(s)); 191 } 192 193 private void createTrue(Element parent) { 194 Document document= parent.getOwnerDocument(); 195 Element type= document.createElement("true"); parent.appendChild(type); 197 } 198 199 private void add(Element dict, String key, String value) { 200 Document document= dict.getOwnerDocument(); 201 Element k= document.createElement("key"); dict.appendChild(k); 203 k.appendChild(document.createTextNode(key)); 204 create(dict, value); 205 } 206 207 private void addTrue(Element dict, String key) { 208 Document document= dict.getOwnerDocument(); 209 Element k= document.createElement("key"); dict.appendChild(k); 211 k.appendChild(document.createTextNode(key)); 212 createTrue(dict); 213 } 214 215 private void pair(Element dict, String outkey, String inkey, String dflt) { 216 String value= null; 217 if (inkey != null) 218 value= fBundleDescription.get(inkey, dflt); 219 else 220 value= dflt; 221 if (value != null && value.trim().length() > 0) { 222 add(dict, outkey, value); 223 } 224 } 225 226 private String processClasspathEntry(File java_dir, String name, int[] id_ref) throws IOException { 227 File f= new File(name); 228 if (f.isDirectory()) { 229 int id= id_ref[0]++; 230 String archivename= "jar_" + id + ".jar"; File to= new File(java_dir, archivename); 232 zip(name, to.getAbsolutePath()); 233 name= archivename; 234 } else { 235 name= copyFile(java_dir, name, null); 236 } 237 return "$JAVAROOT/" + name; } 239 240 private void createPkgInfo(File contents_dir) throws IOException { 241 File pkgInfo= new File(contents_dir, "PkgInfo"); FileOutputStream os= new FileOutputStream(pkgInfo); 243 os.write(("APPL" + fBundleDescription.get(SIGNATURE, "????")).getBytes()); os.close(); 245 } 246 247 private static void deleteDir(File dir) { 248 File[] files= dir.listFiles(); 249 if (files != null) { 250 for (int i= 0; i < files.length; i++) 251 deleteDir(files[i]); 252 } 253 dir.delete(); 254 } 255 256 private File createDir(File parent_dir, String dir_name, boolean remove) throws IOException { 257 File dir= new File(parent_dir, dir_name); 258 if (dir.exists()) { 259 if (!remove) 260 return dir; 261 deleteDir(dir); 262 } 263 if (! dir.mkdir()) 264 throw new IOException("cannot create dir " + dir_name); return dir; 266 } 267 268 private String copyFile(File todir, String fromPath, String toname) throws IOException { 269 if (toname == null) { 270 int pos= fromPath.lastIndexOf('/'); 271 if (pos >= 0) 272 toname= fromPath.substring(pos+1); 273 else 274 toname= fromPath; 275 } 276 File to= new File(todir, toname); 277 fProcesses.add(Runtime.getRuntime().exec(new String [] { "/bin/cp", fromPath, to.getAbsolutePath() })); return toname; 279 } 280 281 private void zip(String dir, String dest) throws IOException { 282 fProcesses.add(Runtime.getRuntime().exec(new String [] { "/usr/bin/jar", "cf", dest, "-C", dir, "." })); } 284 } 285 | Popular Tags |