KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > pde > internal > build > BrandingIron


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.pde.internal.build;
12
13 import java.io.*;
14 import org.eclipse.pde.internal.swt.tools.IconExe;
15
16 /**
17  *
18  */

19 public class BrandingIron implements IXMLConstants {
20     private static final String JavaDoc MARKER_NAME = "%EXECUTABLE_NAME%"; //$NON-NLS-1$
21
private static final String JavaDoc BUNDLE_NAME = "%BUNDLE_NAME%"; //$NON-NLS-1$
22
private static final String JavaDoc ICON_NAME = "%ICON_NAME%"; //$NON-NLS-1$
23
private static final String JavaDoc MARKER_KEY = "<key>CFBundleExecutable</key>"; //$NON-NLS-1$
24
private static final String JavaDoc BUNDLE_KEY = "<key>CFBundleName</key>"; //$NON-NLS-1$
25
private static final String JavaDoc ICON_KEY = "<key>CFBundleIconFile</key>"; //$NON-NLS-1$
26
private static final String JavaDoc STRING_START = "<string>"; //$NON-NLS-1$
27
private static final String JavaDoc STRING_END = "</string>"; //$NON-NLS-1$
28
private static final String JavaDoc XDOC_ICON = "-Xdock:icon=../Resources/Eclipse.icns"; //$NON-NLS-1$
29

30     private String JavaDoc[] icons = null;
31     private String JavaDoc root;
32     private String JavaDoc name;
33     private String JavaDoc os = "win32"; //$NON-NLS-1$
34
private boolean brandIcons = true;
35     
36     public void setName(String JavaDoc value) {
37         name = value;
38     }
39
40     public void setIcons(String JavaDoc value) {
41         icons = value.split(",\\s*"); //$NON-NLS-1$
42
if (icons[0].startsWith("${")) { //$NON-NLS-1$
43
if (icons.length > 1) {
44                 String JavaDoc[] temp = new String JavaDoc[icons.length - 1];
45                 System.arraycopy(icons, 1, temp, 0, temp.length);
46                 icons = temp;
47             } else {
48                 icons = null;
49             }
50         }
51     }
52
53     public void setRoot(String JavaDoc value) {
54         root = value;
55     }
56
57     public void brand() throws Exception JavaDoc {
58         // if the name property is not set it will be ${launcher.name} so just bail.
59
if (name.startsWith("${")) //$NON-NLS-1$
60
return;
61
62         if (icons == null || icons[0].startsWith("${")) //$NON-NLS-1$
63
brandIcons = false;
64         
65         // if the root does not exists (happens in some packaging cases) or
66
// there is already a file with target name and we don't need to update its icons, don't do anything
67
String JavaDoc testName = os.equals("win32") ? name + ".exe" : name; //$NON-NLS-1$ //$NON-NLS-2$
68
if (!new File(root).exists() || (!brandIcons && new File(root, testName).exists()))
69             return;
70         
71         if ("win32".equals(os)) //$NON-NLS-1$
72
brandWindows();
73         if ("linux".equals(os)) //$NON-NLS-1$
74
brandLinux();
75         if ("solaris".equals(os)) //$NON-NLS-1$
76
brandSolaris();
77         if ("macosx".equals(os)) //$NON-NLS-1$
78
brandMac();
79         if ("aix".equals(os)) //$NON-NLS-1$
80
brandAIX();
81         if ("hpux".equals(os)) //$NON-NLS-1$
82
brandHPUX();
83     }
84
85     private void brandAIX() {
86         renameLauncher();
87     }
88
89     private void brandHPUX() {
90         renameLauncher();
91     }
92
93     private void brandLinux() throws Exception JavaDoc {
94         renameLauncher();
95         if (brandIcons)
96             copy(new File(icons[0]), new File(root, "icon.xpm"));
97     }
98
99     private void brandSolaris() throws Exception JavaDoc {
100         renameLauncher();
101         if (brandIcons == false)
102             return;
103         
104         for (int i = 0; i < icons.length; i++) {
105             String JavaDoc icon = icons[i];
106             if (icon.endsWith(".l.pm")) //$NON-NLS-1$
107
copy(new File(icon), new File(root, name + ".l.pm")); //$NON-NLS-1$
108
if (icon.endsWith(".m.pm")) //$NON-NLS-1$
109
copy(new File(icon), new File(root, name + ".m.pm"));
110             if (icon.endsWith(".s.pm"))
111                 copy(new File(icon), new File(root, name + ".s.pm"));
112             if (icon.endsWith(".t.pm"))
113                 copy(new File(icon), new File(root, name + ".t.pm"));
114         }
115     }
116
117     private void brandMac() throws Exception JavaDoc {
118         //Initially the files are in: <root>/Eclipse.app/
119
//and they must appear in <root>/MyAppName.app/
120
//Because java does not support the rename of a folder, files are copied.
121

122         //Initialize the target folders
123
String JavaDoc target = root + '/' + name + ".app/Contents"; //$NON-NLS-1$
124
new File(target).mkdirs();
125         new File(target + "/MacOS").mkdirs();
126         new File(target + "/Resources").mkdirs();
127
128         String JavaDoc initialRoot = root + "/Launcher.app/Contents"; //$NON-NLS-1$
129
if (!new File(initialRoot).exists())
130             initialRoot = root + "/Eclipse.app/Contents"; //$NON-NLS-1$
131
copyMacLauncher(initialRoot, target);
132         String JavaDoc iconName = "";
133         File splashApp = new File(initialRoot, "Resources/Splash.app"); //$NON-NLS-1$
134
if (brandIcons) {
135             File icon = new File(icons[0]);
136             iconName = icon.getName();
137             copy(icon, new File(target + "/Resources/" + icon.getName())); //$NON-NLS-1$
138
new File(initialRoot + "/Resources/Eclipse.icns").delete();
139             if (!splashApp.exists())
140                 new File(initialRoot + "/Resources/").delete(); //$NON-NLS-1$
141
}
142         copyMacIni(initialRoot, target, iconName);
143         modifyInfoPListFile(initialRoot, target, iconName);
144         if (splashApp.exists()) {
145             brandMacSplash(initialRoot, target, iconName);
146         }
147
148         File rootFolder = new File(initialRoot);
149         rootFolder.delete();
150         if (rootFolder.exists()) {
151             //if the rootFolder still exists, its because there were other files that need to be moved over
152
moveContents(rootFolder, new File(target));
153         }
154         rootFolder.getParentFile().delete();
155     }
156
157     
158     /**
159      * Brand the splash.app Info.plist and link or copy the mac launcher.
160      * It is assumed that the mac launcher has been branded already.
161      * @param initialRoot
162      * @param target
163      * @param iconName
164      */

165     private void brandMacSplash(String JavaDoc initialRoot, String JavaDoc target, String JavaDoc iconName) {
166         String JavaDoc splashContents = "/Resources/Splash.app/Contents"; //$NON-NLS-1$
167
modifyInfoPListFile(initialRoot + splashContents, target + splashContents, iconName);
168
169         //link the MacOS launcher for the splash app
170
int result = -1;
171         String JavaDoc osName = System.getProperty("os.name"); //$NON-NLS-1$
172
if (osName != null && !osName.startsWith("Windows")) { //$NON-NLS-1$
173
try {
174                 String JavaDoc [] command = new String JavaDoc [] { "ln", "-sf", "../../../MacOS/" + name, "MacOS/" + name}; //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
175
File linkDir = new File(target, splashContents);
176                 Process JavaDoc proc = Runtime.getRuntime().exec( command, null, linkDir);
177                 result = proc.waitFor();
178             } catch (IOException e) {
179                 // ignore
180
} catch (InterruptedException JavaDoc e) {
181                 // ignore
182
}
183         }
184
185         if (result != 0) {
186             //ln failed, or we are on windows, just copy the executable instead
187
File macOSDir = new File(target, "MacOS"); //$NON-NLS-1$
188
File splashMacOSDir = new File(target, splashContents + "/MacOS"); //$NON-NLS-1$
189
splashMacOSDir.mkdirs();
190             try {
191                 File targetFile = new File(splashMacOSDir, name);
192                 copy(new File(macOSDir, name), targetFile);
193                 try {
194                     Runtime.getRuntime().exec(new String JavaDoc[] {"chmod", "755", targetFile.getAbsolutePath()}); //$NON-NLS-1$ //$NON-NLS-2$
195
} catch (IOException e) {
196                     // ignore
197
}
198             } catch (IOException e) {
199                 System.out.println("Could not copy macosx splash launcher"); //$NON-NLS-1$
200
}
201         }
202     }
203     
204     private void moveContents(File source, File target) {
205         if (!source.exists())
206             return;
207
208         try {
209             if (source.getCanonicalFile().equals(target.getCanonicalFile()))
210                 return;
211         } catch (IOException e) {
212             System.out.println("Could not copy macosx resources."); //$NON-NLS-1$
213
return;
214         }
215
216         target.getParentFile().mkdirs();
217         if (source.isDirectory()) {
218             target.mkdirs();
219             File[] contents = source.listFiles();
220             for (int i = 0; i < contents.length; i++) {
221                 File dest = new File(target, contents[i].getName());
222                 if (contents[i].isFile())
223                     contents[i].renameTo(dest);
224                 else
225                     moveContents(contents[i], dest);
226             }
227             source.delete();
228         } else {
229             source.renameTo(target);
230         }
231     }
232
233     private void brandWindows() throws Exception JavaDoc {
234         File templateLauncher = new File(root, "launcher.exe");
235         if (!templateLauncher.exists())
236             templateLauncher = new File(root, "eclipse.exe");
237         if (brandIcons) {
238             String JavaDoc[] args = new String JavaDoc[icons.length + 1];
239             args[0] = templateLauncher.getAbsolutePath();
240             System.arraycopy(icons, 0, args, 1, icons.length);
241             IconExe.main(args);
242         }
243         templateLauncher.renameTo(new File(root, name + ".exe"));
244     }
245
246     private void renameLauncher() {
247         if (!new File(root, "launcher").renameTo(new File(root, name)))
248             new File(root, "eclipse").renameTo(new File(root, name));
249     }
250
251     private void copyMacLauncher(String JavaDoc initialRoot, String JavaDoc target) {
252         String JavaDoc targetLauncher = target + "/MacOS/";
253         File launcher = new File(initialRoot + "/MacOS/launcher");
254         File eclipseLauncher = new File(initialRoot + "/MacOS/eclipse"); //$NON-NLS-1$
255
if (!launcher.exists()) {
256             launcher = eclipseLauncher;
257         } else if (eclipseLauncher.exists()) {
258             //we may actually have both if exporting from the mac
259
eclipseLauncher.delete();
260         }
261         File targetFile = new File(targetLauncher, name);
262         try {
263             if (targetFile.getCanonicalFile().equals(launcher.getCanonicalFile())) {
264                 try {
265                     //Force the executable bit on the exe because it has been lost when copying the file
266
Runtime.getRuntime().exec(new String JavaDoc[] {"chmod", "755", targetFile.getAbsolutePath()}); //$NON-NLS-1$ //$NON-NLS-2$
267
} catch (IOException e) {
268                     //ignore
269
}
270                 return;
271             }
272             copy(launcher, targetFile);
273         } catch (IOException e) {
274             System.out.println("Could not copy macosx launcher");
275             return;
276         }
277         try {
278             //Force the executable bit on the exe because it has been lost when copying the file
279
Runtime.getRuntime().exec(new String JavaDoc[] {"chmod", "755", targetFile.getAbsolutePath()}); //$NON-NLS-1$ //$NON-NLS-2$
280
} catch (IOException e) {
281             //ignore
282
}
283         launcher.delete();
284         launcher.getParentFile().delete();
285     }
286
287     private void copyMacIni(String JavaDoc initialRoot, String JavaDoc target, String JavaDoc iconName) {
288         File brandedIni = new File(initialRoot, "/MacOS/" + name + ".ini"); //$NON-NLS-1$ //$NON-NLS-2$
289

290         File ini = new File(initialRoot, "/MacOS/eclipse.ini"); //$NON-NLS-1$
291
if (!ini.exists() && !brandedIni.exists())
292             return;
293         
294         if (brandedIni.exists() && ini.exists()) {
295             //take the one that is already branded
296
ini.delete();
297             ini = brandedIni;
298         }
299
300         StringBuffer JavaDoc buffer;
301         try {
302             buffer = readFile(ini);
303             ini.delete();
304         } catch (IOException e) {
305             System.out.println("Impossible to brand ini file"); //$NON-NLS-1$
306
return;
307         }
308
309         if(iconName.length() > 0){
310             int xdoc = scan(buffer, 0, XDOC_ICON);
311             if (xdoc != -1) {
312                 String JavaDoc icns = XDOC_ICON.replaceFirst("Eclipse.icns", iconName); //$NON-NLS-1$
313
buffer.replace(xdoc, xdoc + XDOC_ICON.length(), icns);
314             }
315         }
316
317         try {
318             File targetFile = new File(target, "/MacOS/" + name + ".ini"); //$NON-NLS-1$//$NON-NLS-2$
319
transferStreams(new ByteArrayInputStream(buffer.toString().getBytes()), new FileOutputStream(targetFile));
320         } catch (FileNotFoundException e) {
321             System.out.println("Impossible to brand ini file"); //$NON-NLS-1$
322
return;
323         } catch (IOException e) {
324             System.out.println("Impossible to brand ini file"); //$NON-NLS-1$
325
return;
326         }
327     }
328
329     private void modifyInfoPListFile(String JavaDoc initialRoot, String JavaDoc targetRoot, String JavaDoc iconName) {
330         File infoPList = new File(initialRoot, "Info.plist"); //$NON-NLS-1$
331
StringBuffer JavaDoc buffer;
332         try {
333             buffer = readFile(infoPList);
334         } catch (IOException e) {
335             System.out.println("Impossible to brand info.plist file"); //$NON-NLS-1$
336
return;
337         }
338         int exePos = scan(buffer, 0, MARKER_NAME);
339         if (exePos != -1)
340             buffer.replace(exePos, exePos + MARKER_NAME.length(), name);
341         else {
342             exePos = scan(buffer, 0, MARKER_KEY);
343             if (exePos != -1) {
344                 int start = scan(buffer, exePos + MARKER_KEY.length(), STRING_START);
345                 int end = scan(buffer, start + STRING_START.length(), STRING_END);
346                 if (start > -1 && end > start) {
347                     buffer.replace(start + STRING_START.length(), end, name);
348                 }
349             }
350         }
351
352         int bundlePos = scan(buffer, 0, BUNDLE_NAME);
353         if (bundlePos != -1)
354             buffer.replace(bundlePos, bundlePos + BUNDLE_NAME.length(), name);
355         else {
356             exePos = scan(buffer, 0, BUNDLE_KEY);
357             if (exePos != -1) {
358                 int start = scan(buffer, exePos + BUNDLE_KEY.length(), STRING_START);
359                 int end = scan(buffer, start + STRING_START.length(), STRING_END);
360                 if (start > -1 && end > start) {
361                     buffer.replace(start + STRING_START.length(), end, name);
362                 }
363             }
364         }
365
366         int iconPos = scan(buffer, 0, ICON_NAME);
367         if (iconPos != -1)
368             buffer.replace(iconPos, iconPos + ICON_NAME.length(), iconName);
369         else {
370             exePos = scan(buffer, 0, ICON_KEY);
371             if (exePos != -1) {
372                 int start = scan(buffer, exePos + ICON_KEY.length(), STRING_START);
373                 int end = scan(buffer, start + STRING_START.length(), STRING_END);
374                 if (start > -1 && end > start) {
375                     buffer.replace(start + STRING_START.length(), end, iconName);
376                 }
377             }
378         }
379
380         File target = null;
381         try {
382             target = new File(targetRoot, "Info.plist");
383             target.getParentFile().mkdirs();
384             transferStreams(new ByteArrayInputStream(buffer.toString().getBytes()), new FileOutputStream(target));
385         } catch (FileNotFoundException e) {
386             System.out.println("Impossible to brand info.plist file"); //$NON-NLS-1$
387
return;
388         } catch (IOException e) {
389             System.out.println("Impossible to brand info.plist file"); //$NON-NLS-1$
390
return;
391         }
392         try {
393             if (!infoPList.getCanonicalFile().equals(target.getCanonicalFile()))
394                 infoPList.delete();
395         } catch (IOException e) {
396             //ignore
397
}
398     }
399
400     /**
401      * Transfers all available bytes from the given input stream to the given output stream.
402      * Regardless of failure, this method closes both streams.
403      * @throws IOException
404      */

405     public void copy(File source, File destination) throws IOException {
406         InputStream in = null;
407         OutputStream out = null;
408         try {
409             in = new BufferedInputStream(new FileInputStream(source));
410             out = new BufferedOutputStream(new FileOutputStream(destination));
411             final byte[] buffer = new byte[8192];
412             while (true) {
413                 int bytesRead = -1;
414                 bytesRead = in.read(buffer);
415                 if (bytesRead == -1)
416                     break;
417                 out.write(buffer, 0, bytesRead);
418             }
419         } finally {
420             try {
421                 if (in != null)
422                     in.close();
423             } finally {
424                 if (out != null)
425                     out.close();
426             }
427         }
428     }
429
430     private int scan(StringBuffer JavaDoc buf, int start, String JavaDoc targetName) {
431         return scan(buf, start, new String JavaDoc[] {targetName});
432     }
433
434     private int scan(StringBuffer JavaDoc buf, int start, String JavaDoc[] targets) {
435         for (int i = start; i < buf.length(); i++) {
436             for (int j = 0; j < targets.length; j++) {
437                 if (i < buf.length() - targets[j].length()) {
438                     String JavaDoc match = buf.substring(i, i + targets[j].length());
439                     if (targets[j].equalsIgnoreCase(match))
440                         return i;
441                 }
442             }
443         }
444         return -1;
445     }
446
447     private StringBuffer JavaDoc readFile(File targetName) throws IOException {
448         InputStreamReader reader = new InputStreamReader(new BufferedInputStream(new FileInputStream(targetName)));
449         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
450         char[] buf = new char[4096];
451         int count;
452         try {
453             count = reader.read(buf, 0, buf.length);
454             while (count != -1) {
455                 result.append(buf, 0, count);
456                 count = reader.read(buf, 0, buf.length);
457             }
458         } finally {
459             try {
460                 reader.close();
461             } catch (IOException e) {
462                 // ignore exceptions here
463
}
464         }
465         return result;
466     }
467
468     private void transferStreams(InputStream source, OutputStream destination) throws IOException {
469         source = new BufferedInputStream(source);
470         destination = new BufferedOutputStream(destination);
471         try {
472             byte[] buffer = new byte[8192];
473             while (true) {
474                 int bytesRead = -1;
475                 if ((bytesRead = source.read(buffer)) == -1)
476                     break;
477                 destination.write(buffer, 0, bytesRead);
478             }
479         } finally {
480             try {
481                 source.close();
482             } catch (IOException e) {
483                 // ignore
484
}
485             try {
486                 destination.close();
487             } catch (IOException e) {
488                 // ignore
489
}
490         }
491     }
492
493     public void setOS(String JavaDoc value) {
494         os = value;
495     }
496 }
497
Popular Tags