1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.devzendo.xplp;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.Properties;
25 import java.util.Set;
26
27 import org.apache.maven.artifact.Artifact;
28 import org.apache.maven.plugin.AbstractMojo;
29
30
31
32
33
34
35
36
37
38
39
40 public final class MacOSXAppLauncherCreator extends LauncherCreator {
41 private static final String LINE_SEPARATOR = System.getProperty("line.separator");
42 public static final String APPLE_STUB = "Apple";
43 public static final String UNIVERSAL_STUB = "Universal";
44 private final String mFileType;
45 private final String mIconsFileName;
46 private final String mBundleSignature;
47 private final String mBundleOsType;
48 private final String mBundleTypeName;
49 private final String mLauncherType;
50 private final String mStubType;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public MacOSXAppLauncherCreator(final AbstractMojo mojo,
73 final File outputDirectory,
74 final String mainClassName,
75 final String applicationName,
76 final String libraryDirectory,
77 final Set<Artifact> transitiveArtifacts,
78 final Set<File> resourceDirectories,
79 final Properties parameterProperties,
80 final String[] systemProperties,
81 final String[] vmArguments,
82 final String[] narClassifierTypes,
83 final String launcherType,
84 final String fileType,
85 final String iconsFileName,
86 final String bundleSignature,
87 final String bundleOsType,
88 final String bundleTypeName,
89 final String stubType) {
90 super(mojo, outputDirectory, mainClassName,
91 applicationName, libraryDirectory,
92 transitiveArtifacts, resourceDirectories,
93 parameterProperties, systemProperties, vmArguments,
94 narClassifierTypes);
95 mFileType = fileType;
96 mIconsFileName = iconsFileName;
97 mBundleSignature = bundleSignature;
98 mBundleOsType = bundleOsType;
99 mBundleTypeName = bundleTypeName;
100 mLauncherType = launcherType;
101 mStubType = stubType;
102 }
103
104 private void validate() {
105 if (mIconsFileName == null || mIconsFileName.length() == 0) {
106 final String message = "No iconsFileName specified - this is mandatory for Mac OS X";
107 getMojo().getLog().warn(message);
108 throw new IllegalStateException(message);
109 }
110 if (mBundleSignature == null || mBundleSignature.length() == 0) {
111 final String message = "No bundleSignature specified - this is mandatory for Mac OS X";
112 getMojo().getLog().warn(message);
113 throw new IllegalStateException(message);
114 }
115 if (mStubType == null || ((!mStubType.equals(APPLE_STUB)) && (!mStubType.equals(UNIVERSAL_STUB))) ) {
116 final String message = "Stub type must be '" + APPLE_STUB + "' or '" + UNIVERSAL_STUB + "'";
117 getMojo().getLog().warn(message);
118 throw new IllegalStateException(message);
119 }
120 }
121
122
123
124
125 @Override
126 public void createLauncher() throws IOException {
127 validate();
128 getParameterProperties().put("xplp.macosxsystemproperties", systemPropertiesAsPlistDict(getSystemProperties()));
129 getParameterProperties().put("xplp.macosxvmoptionsarray", vmArgumentsAsPlistArray(getVmArguments()));
130 getParameterProperties().put("xplp.macosxclasspatharray", transitiveArtifactsAsPlistArray(getTransitiveArtifacts()));
131
132 getMojo().getLog().info("Launcher type: " + mLauncherType);
133 getMojo().getLog().info("Icons file name: " + mIconsFileName);
134 getMojo().getLog().info("File type: " + mFileType);
135 getMojo().getLog().info("Bundle signature: " + mBundleSignature);
136 getMojo().getLog().info("Bundle OS type: " + mBundleOsType);
137 getMojo().getLog().info("Bundle type name: " + mBundleTypeName);
138 getMojo().getLog().info("Stub type: " + mStubType);
139
140 final File osOutputDir = new File(getOutputDirectory(), "macosx");
141 final File appDir = new File(osOutputDir, getApplicationName() + ".app");
142 final File contentsDir = new File(appDir, "Contents");
143 final File macOSDir = new File(contentsDir, "MacOS");
144 final File resourcesDir = new File(contentsDir, "Resources");
145 final File libDir = new File(resourcesDir, "Java/lib");
146 osOutputDir.mkdirs();
147 appDir.mkdirs();
148 contentsDir.mkdirs();
149 macOSDir.mkdirs();
150 resourcesDir.mkdirs();
151 libDir.mkdirs();
152 final boolean allDirsOK = osOutputDir.exists()
153 && appDir.exists() && contentsDir.exists()
154 && macOSDir.exists() && resourcesDir.exists()
155 && libDir.exists();
156 if (!allDirsOK) {
157 throw new IOException("Could not create required directories under " + appDir.getAbsolutePath());
158 }
159
160 final File javaApplicationStub = new File(macOSDir, "JavaApplicationStub");
161 if (mStubType.equals(APPLE_STUB)) {
162 copyPluginResource("macosx/JavaApplicationStub", javaApplicationStub);
163 }
164 if (mStubType.equals(UNIVERSAL_STUB)) {
165 copyPluginResource("macosx/universalJavaApplicationStub", javaApplicationStub);
166 }
167 makeExecutable(javaApplicationStub);
168
169 copyProjectResource(mIconsFileName, new File(resourcesDir, mIconsFileName));
170
171 copyInterpolatedPluginResource("macosx/Info.plist", new File(contentsDir, "Info.plist"));
172 copyInterpolatedPluginResource("macosx/PkgInfo", new File(contentsDir, "PkgInfo"));
173
174 copyTransitiveArtifacts(libDir);
175 }
176
177 private String vmArgumentsAsPlistArray(final String[] vmArguments) {
178 final StringBuilder argsAsArray = new StringBuilder();
179 if (vmArguments.length > 0) {
180 argsAsArray.append(" <key>VMOptions</key>");
181 argsAsArray.append(LINE_SEPARATOR);
182 argsAsArray.append(" <array>");
183 argsAsArray.append(LINE_SEPARATOR);
184 for (final String vmArg : vmArguments) {
185 argsAsArray.append(" <string>");
186 argsAsArray.append(vmArg);
187 argsAsArray.append("</string>");
188 argsAsArray.append(LINE_SEPARATOR);
189 }
190 argsAsArray.append(" </array>");
191 argsAsArray.append(LINE_SEPARATOR);
192 }
193 return argsAsArray.toString();
194 }
195
196 private String systemPropertiesAsPlistDict(final String[] systemProperties) {
197 final StringBuilder propsAsDictEntries = new StringBuilder();
198 for (int i = 0; i < systemProperties.length; i++) {
199 final String prop = systemProperties[i];
200 appendSystemProperty(propsAsDictEntries, prop);
201 propsAsDictEntries.append(LINE_SEPARATOR);
202 }
203 return propsAsDictEntries.toString();
204 }
205
206 private void appendSystemProperty(
207 final StringBuilder propsAsDictEntries,
208 final String prop) {
209 final String[] split = prop.split("\\s*=\\s*");
210 propsAsDictEntries.append(" <key>");
211 propsAsDictEntries.append(split[0]);
212 propsAsDictEntries.append("</key>");
213 propsAsDictEntries.append(LINE_SEPARATOR);
214 propsAsDictEntries.append(" <string>");
215 propsAsDictEntries.append(split[1]);
216 propsAsDictEntries.append("</string>");
217 }
218
219 private String transitiveArtifactsAsPlistArray(final Set<Artifact> transitiveArtifacts) {
220 final StringBuilder libsAsArtifacts = new StringBuilder();
221 final Set<String> transitiveArtifactFileNames = getTransitiveJarOrNarArtifactFileNames(transitiveArtifacts);
222 for (final String fileName : transitiveArtifactFileNames) {
223 libsAsArtifacts.append(" <string>$JAVAROOT/lib/");
224 libsAsArtifacts.append(fileName);
225 libsAsArtifacts.append("</string>");
226 libsAsArtifacts.append(LINE_SEPARATOR);
227 }
228
229 return libsAsArtifacts.toString();
230 }
231 }