PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/net/sourceforge/jarbundler/PropertyListWriter.java

#
Java | 442 lines | 241 code | 130 blank | 71 comment | 53 complexity | 068d85a91bc468112f9aed2f5ce8b73d MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * Write the application bundle file: Info.plist
  3. *
  4. * Copyright (c) 2006, William A. Gilbert <gilbert@informagen.com> All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the Free
  8. * Software Foundation; either version 2 of the License, or (at your option)
  9. * any later version.
  10. *
  11. * This program 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 for
  14. * more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along with
  17. * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  18. * Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. package net.sourceforge.jarbundler;
  21. // This package's imports
  22. import net.sourceforge.jarbundler.AppBundleProperties;
  23. // Java I/O
  24. import java.io.BufferedWriter;
  25. import java.io.File;
  26. import java.io.FileOutputStream;
  27. import java.io.IOException;
  28. import java.io.OutputStreamWriter;
  29. import java.io.Writer;
  30. // Java Utility
  31. import java.util.Hashtable;
  32. import java.util.Iterator;
  33. import java.util.List;
  34. // Java language imports
  35. import java.lang.Boolean;
  36. import java.lang.ClassCastException;
  37. import java.lang.Double;
  38. import java.lang.String;
  39. import java.lang.System;
  40. // Apache Ant
  41. import org.apache.tools.ant.BuildException;
  42. import org.apache.tools.ant.util.FileUtils;
  43. // Java XML DOM creation
  44. import javax.xml.parsers.DocumentBuilderFactory;
  45. import javax.xml.parsers.DocumentBuilder;
  46. import javax.xml.parsers.ParserConfigurationException;
  47. // W3C DOM
  48. import org.w3c.dom.Document;
  49. import org.w3c.dom.DOMImplementation;
  50. import org.w3c.dom.Node;
  51. import org.w3c.dom.Element;
  52. import org.w3c.dom.Attr;
  53. // Xerces serializer
  54. import org.apache.xml.serialize.OutputFormat;
  55. import org.apache.xml.serialize.XMLSerializer;
  56. import org.apache.xml.serialize.LineSeparator;
  57. /**
  58. * Write out a Java application bundle property list file. For descriptions of
  59. * the property list keys, see <a
  60. * href="http://developer.apple.com/documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/PListKeys.html"
  61. * >Apple docs</a>.
  62. */
  63. public class PropertyListWriter {
  64. // Our application bundle properties
  65. private AppBundleProperties bundleProperties;
  66. private double version = 1.3;
  67. // DOM version of Info.plist file
  68. private Document document = null;
  69. private FileUtils fileUtils = FileUtils.getFileUtils();
  70. /**
  71. * Create a new Property List writer.
  72. */
  73. public PropertyListWriter(AppBundleProperties bundleProperties) {
  74. this.bundleProperties = bundleProperties;
  75. setJavaVersion(bundleProperties.getJVMVersion());
  76. }
  77. private void setJavaVersion(String version) {
  78. if (version == null)
  79. return;
  80. this.version = Double.valueOf(version.substring(0, 3)).doubleValue();
  81. }
  82. public void writeFile(File fileName) throws BuildException {
  83. Writer writer = null;
  84. try {
  85. this.document = createDOM();
  86. buildDOM();
  87. // Serialize the DOM into the writer
  88. writer = new BufferedWriter(new OutputStreamWriter(
  89. new FileOutputStream(fileName), "UTF-8"));
  90. // Prettify the XML Two space indenting, no line wrapping
  91. OutputFormat outputFormat = new OutputFormat();
  92. outputFormat.setMethod("xml");
  93. outputFormat.setIndenting(true);
  94. outputFormat.setIndent(2);
  95. outputFormat.setLineWidth(0);
  96. // Create a DOM serlializer and write the XML
  97. XMLSerializer serializer = new XMLSerializer(writer, outputFormat);
  98. serializer.asDOMSerializer();
  99. serializer.serialize(this.document);
  100. } catch (ParserConfigurationException pce) {
  101. throw new BuildException(pce);
  102. } catch (IOException ex) {
  103. throw new BuildException("Unable to write \"" + fileName + "\"");
  104. } finally {
  105. fileUtils.close(writer);
  106. }
  107. }
  108. private Document createDOM() throws ParserConfigurationException {
  109. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  110. DocumentBuilder documentBuilder = factory.newDocumentBuilder();
  111. DOMImplementation domImpl = documentBuilder.getDOMImplementation();
  112. // We needed to reference using the full class name here because we already have
  113. // a class named "DocumentType"
  114. org.w3c.dom.DocumentType doctype = domImpl.createDocumentType(
  115. "plist",
  116. "-//Apple Computer//DTD PLIST 1.0//EN",
  117. "http://www.apple.com/DTDs/PropertyList-1.0.dtd");
  118. return domImpl.createDocument(null, "plist", doctype);
  119. }
  120. private void buildDOM() {
  121. Element plist = this.document.getDocumentElement();
  122. plist.setAttribute("version","1.0");
  123. // Open the top level dictionary, <dict>
  124. Node dict = createNode("dict", plist);
  125. // Application short name i.e. About menu name
  126. writeKeyStringPair("CFBundleName", bundleProperties.getCFBundleName(), dict);
  127. // Finder 'Version' label, defaults to "1.0"
  128. writeKeyStringPair("CFBundleShortVersionString", bundleProperties.getCFBundleShortVersionString(), dict);
  129. // Finder 'Get Info'
  130. writeKeyStringPair("CFBundleGetInfoString", bundleProperties.getCFBundleGetInfoString(), dict);
  131. // Mac OS X required key, defaults to "false"
  132. writeKeyStringPair("CFBundleAllowMixedLocalizations",
  133. (bundleProperties.getCFBundleAllowMixedLocalizations() ? "true" : "false"),
  134. dict);
  135. // Mac OS X required, defaults to "6.0"
  136. writeKeyStringPair("CFBundleInfoDictionaryVersion",
  137. bundleProperties.getCFBundleInfoDictionaryVersion(), dict);
  138. // Bundle Executable name, required, defaults to "JavaApplicationStub"
  139. writeKeyStringPair("CFBundleExecutable", bundleProperties.getCFBundleExecutable(), dict);
  140. // Bundle Development Region, required, defaults to "English"
  141. writeKeyStringPair("CFBundleDevelopmentRegion", bundleProperties.getCFBundleDevelopmentRegion(), dict);
  142. // Bundle Package Type, required, defaults tp "APPL"
  143. writeKeyStringPair("CFBundlePackageType", bundleProperties.getCFBundlePackageType(), dict);
  144. // Bundle Signature, required, defaults tp "????"
  145. writeKeyStringPair("CFBundleSignature", bundleProperties.getCFBundleSignature(), dict);
  146. // Application build number, optional
  147. if (bundleProperties.getCFBundleVersion() != null)
  148. writeKeyStringPair("CFBundleVersion", bundleProperties.getCFBundleVersion(), dict);
  149. // Application Icon file, optional
  150. if (bundleProperties.getCFBundleIconFile() != null)
  151. writeKeyStringPair("CFBundleIconFile", bundleProperties.getCFBundleIconFile(), dict);
  152. // Bundle Identifier, optional
  153. if (bundleProperties.getCFBundleIdentifier() != null)
  154. writeKeyStringPair("CFBundleIdentifier", bundleProperties.getCFBundleIdentifier(), dict);
  155. // Help Book Folder, optional
  156. if (bundleProperties.getCFBundleHelpBookFolder() != null)
  157. writeKeyStringPair("CFBundleHelpBookFolder", bundleProperties.getCFBundleHelpBookFolder(), dict);
  158. // Help Book Name, optional
  159. if (bundleProperties.getCFBundleHelpBookName() != null)
  160. writeKeyStringPair("CFBundleHelpBookName", bundleProperties.getCFBundleHelpBookName(), dict);
  161. // Document Types, optional
  162. List documentTypes = bundleProperties.getDocumentTypes();
  163. if (documentTypes.size() > 0)
  164. writeDocumentTypes(documentTypes, dict);
  165. // Java entry in the plist dictionary
  166. writeKey("Java", dict);
  167. Node javaDict = createNode("dict", dict);
  168. // Main class, required
  169. writeKeyStringPair("MainClass", bundleProperties.getMainClass(), javaDict);
  170. // Target JVM version, optional but recommended
  171. if (bundleProperties.getJVMVersion() != null)
  172. writeKeyStringPair("JVMVersion", bundleProperties.getJVMVersion(), javaDict);
  173. // Classpath is composed of two types, required
  174. // 1: Jars bundled into the JAVA_ROOT of the application
  175. // 2: External directories or files with an absolute path
  176. List classPath = bundleProperties.getClassPath();
  177. List extraClassPath = bundleProperties.getExtraClassPath();
  178. if ((classPath.size() > 0) || (extraClassPath.size() > 0))
  179. writeClasspath(classPath, extraClassPath, javaDict);
  180. // JVM options, optional
  181. if (bundleProperties.getVMOptions() != null)
  182. writeKeyStringPair("VMOptions", bundleProperties.getVMOptions(), javaDict);
  183. // Working directory, optional
  184. if (bundleProperties.getWorkingDirectory() != null)
  185. writeKeyStringPair("WorkingDirectory", bundleProperties.getWorkingDirectory(), javaDict);
  186. // Main class arguments, optional
  187. if (bundleProperties.getArguments() != null)
  188. writeKeyStringPair("Arguments", bundleProperties.getArguments(), javaDict);
  189. // Java properties, optional
  190. Hashtable javaProperties = bundleProperties.getJavaProperties();
  191. if (javaProperties.isEmpty() == false)
  192. writeJavaProperties(javaProperties, javaDict);
  193. // Services, optional
  194. List services = bundleProperties.getServices();
  195. if (services.size() > 0)
  196. writeServices(services,dict);
  197. }
  198. private void writeDocumentTypes(List documentTypes, Node appendTo) {
  199. writeKey("CFBundleDocumentTypes", appendTo);
  200. Node array = createNode("array", appendTo);
  201. Iterator itor = documentTypes.iterator();
  202. while (itor.hasNext()) {
  203. DocumentType documentType = (DocumentType) itor.next();
  204. Node documentDict = createNode("dict", array);
  205. writeKeyStringPair("CFBundleTypeName", documentType.getName(), documentDict);
  206. writeKeyStringPair("CFBundleTypeRole", documentType.getRole(), documentDict);
  207. File iconFile = documentType.getIconFile();
  208. if (iconFile != null)
  209. writeKeyStringPair("CFBundleTypeIconFile", iconFile.getName(), documentDict);
  210. List extensions = documentType.getExtensions();
  211. if (extensions.isEmpty() == false) {
  212. writeKey("CFBundleTypeExtensions", documentDict);
  213. writeArray(extensions, documentDict);
  214. }
  215. List osTypes = documentType.getOSTypes();
  216. if (osTypes.isEmpty() == false) {
  217. writeKey("CFBundleTypeOSTypes", documentDict);
  218. writeArray(osTypes, documentDict);
  219. }
  220. List mimeTypes = documentType.getMimeTypes();
  221. if (mimeTypes.isEmpty() == false) {
  222. writeKey("CFBundleTypeMIMETypes", documentDict);
  223. writeArray(mimeTypes, documentDict);
  224. }
  225. // Only write this key if true
  226. if (documentType.isBundle())
  227. writeKeyStringPair("LSTypeIsPackage", "true", documentDict);
  228. }
  229. }
  230. private void writeServices(List services, Node appendTo) {
  231. writeKey("NSServices",appendTo);
  232. Node array = createNode("array",appendTo);
  233. Iterator itor = services.iterator();
  234. while (itor.hasNext()) {
  235. Service service = (Service)itor.next();
  236. Node serviceDict = createNode("dict",array);
  237. String portName = service.getPortName();
  238. if (portName == null)
  239. portName = bundleProperties.getCFBundleName();
  240. writeKeyStringPair("NSPortName", portName, serviceDict);
  241. writeKeyStringPair("NSMessage",service.getMessage(),serviceDict);
  242. List sendTypes = service.getSendTypes();
  243. if (!sendTypes.isEmpty()) {
  244. writeKey("NSSendTypes",serviceDict);
  245. writeArray(sendTypes,serviceDict);
  246. }
  247. List returnTypes = service.getReturnTypes();
  248. if (!returnTypes.isEmpty()) {
  249. writeKey("NSReturnTypes",serviceDict);
  250. writeArray(returnTypes,serviceDict);
  251. }
  252. writeKey("NSMenuItem",serviceDict);
  253. Node menuItemDict = createNode("dict",serviceDict);
  254. writeKeyStringPair("default",service.getMenuItem(),menuItemDict);
  255. String keyEquivalent = service.getKeyEquivalent();
  256. if (null != keyEquivalent) {
  257. writeKey("NSKeyEquivalent",serviceDict);
  258. Node keyEquivalentDict = createNode("dict",serviceDict);
  259. writeKeyStringPair("default",keyEquivalent,keyEquivalentDict);
  260. }
  261. String userData = service.getUserData();
  262. if (null != userData)
  263. writeKeyStringPair("NSUserData", userData, serviceDict);
  264. String timeout = service.getTimeout();
  265. if (null != timeout)
  266. writeKeyStringPair("NSTimeout",timeout,serviceDict);
  267. }
  268. }
  269. private void writeClasspath(List classpath, List extraClasspath, Node appendTo) {
  270. writeKey("ClassPath", appendTo);
  271. classpath.addAll(extraClasspath);
  272. writeArray(classpath, appendTo);
  273. }
  274. private void writeJavaProperties(Hashtable javaProperties, Node appendTo) {
  275. writeKey("Properties", appendTo);
  276. Node propertiesDict = createNode("dict", appendTo);
  277. for (Iterator i = javaProperties.keySet().iterator(); i.hasNext();) {
  278. String key = (String) i.next();
  279. if (key.startsWith("com.apple.") && (version >= 1.4)) {
  280. System.out.println("Deprecated as of 1.4: " + key);
  281. continue;
  282. }
  283. writeKeyStringPair(key, (String)javaProperties.get(key), propertiesDict);
  284. }
  285. }
  286. private Node createNode(String tag, Node appendTo) {
  287. Node node = this.document.createElement(tag);
  288. appendTo.appendChild(node);
  289. return node;
  290. }
  291. private void writeKeyStringPair(String key, String string, Node appendTo) {
  292. if (string == null)
  293. return;
  294. writeKey(key, appendTo);
  295. writeString(string, appendTo);
  296. }
  297. private void writeKey(String key, Node appendTo) {
  298. Element keyNode = this.document.createElement("key");
  299. appendTo.appendChild(keyNode);
  300. keyNode.appendChild(this.document.createTextNode(key));
  301. }
  302. private void writeString(String string, Node appendTo) {
  303. Element stringNode = this.document.createElement("string");
  304. stringNode.appendChild(this.document.createTextNode(string));
  305. appendTo.appendChild(stringNode);
  306. }
  307. private void writeArray(List stringList, Node appendTo) {
  308. Node arrayNode = createNode("array", appendTo);
  309. for (Iterator it = stringList.iterator(); it.hasNext();)
  310. writeString((String)it.next(), arrayNode);
  311. }
  312. }