IDEA-117841 Make launcher reflect the true product
[idea/community.git] / tools / launcher-generator / src / com / pme / launcher / LauncherGeneratorMain.java
1 /*
2  * Copyright 2006 ProductiveMe Inc.
3  * Copyright 2013 JetBrains s.r.o.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package com.pme.launcher;
19
20 import org.apache.sanselan.ImageFormat;
21 import org.apache.sanselan.Sanselan;
22 import org.jdom.Document;
23 import org.jdom.Element;
24 import org.jdom.input.SAXBuilder;
25
26 import java.awt.image.BufferedImage;
27 import java.io.*;
28 import java.nio.charset.Charset;
29 import java.util.*;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32
33 /**
34  * @author yole
35  */
36 public class LauncherGeneratorMain {
37   public static void main(String[] args) {
38     if (args.length != 5) {
39       System.err.println("Usage: LauncherGeneratorMain <template EXE file> <app info file> <resource.h file> <properties> <output>");
40       System.exit(1);
41     }
42
43     File template = new File(args[0]);
44     if (!template.exists()) {
45       System.err.println("Launcher template EXE file " + args[0] + " not found");
46       System.exit(2);
47     }
48
49     String appInfoFileName = args[1];
50     InputStream appInfoStream;
51     try {
52       appInfoStream = new FileInputStream(appInfoFileName);
53     }
54     catch (FileNotFoundException e) {
55       appInfoStream = LauncherGeneratorMain.class.getClassLoader().getResourceAsStream(appInfoFileName);
56     }
57
58     if (appInfoStream == null) {
59       System.err.println("Application info file " + appInfoFileName + " not found");
60       System.exit(3);
61     }
62     Document appInfo;
63     try {
64       appInfo = new SAXBuilder().build(appInfoStream);
65     } catch (Exception e) {
66       System.err.println("Error loading application info file " + appInfoFileName + ": " + e.getMessage());
67       System.exit(4);
68       return;
69     }
70
71     Element appInfoRoot = appInfo.getRootElement();
72     String splashUrl = appInfoRoot.getChild("logo").getAttributeValue("url");
73     if (splashUrl.startsWith("/")) {
74       splashUrl = splashUrl.substring(1);
75     }
76     InputStream splashStream = LauncherGeneratorMain.class.getClassLoader().getResourceAsStream(splashUrl);
77     if (splashStream == null) {
78       System.err.println("Splash screen image file file " + splashUrl + " not found");
79       System.exit(5);
80     }
81
82     ByteArrayOutputStream splashBmpStream = new ByteArrayOutputStream();
83     try {
84       BufferedImage bufferedImage = Sanselan.getBufferedImage(splashStream);
85       Sanselan.writeImage(bufferedImage, splashBmpStream, ImageFormat.IMAGE_FORMAT_BMP, new HashMap());
86     }
87     catch (Exception e) {
88       System.err.println("Error converting splash screen to BMP: " + e.getMessage());
89       System.exit(6);
90     }
91
92     String icoUrl = appInfoRoot.getChild("icon").getAttributeValue("ico");
93     if (icoUrl == null) {
94       System.err.println(".ico file URL not specified in application info file " + appInfoFileName);
95       System.exit(11);
96     }
97     InputStream iconStream = LauncherGeneratorMain.class.getClassLoader().getResourceAsStream(icoUrl);
98     if (iconStream == null) {
99       System.err.println(".ico file " + icoUrl + " not found");
100       System.exit(12);
101     }
102
103     Map<String, Integer> resourceIDs;
104     try {
105       resourceIDs = loadResourceIDs(args[2]);
106     }
107     catch (Exception e) {
108       System.err.println("Error loading resource.h: " + e.getMessage());
109       System.exit(7);
110       return;
111     }
112
113     Properties properties = new Properties();
114     try {
115       FileInputStream fis = new FileInputStream(args[3]);
116       try {
117         properties.load(fis);
118       }
119       finally {
120         fis.close();
121       }
122     }
123     catch (IOException e) {
124       System.err.println("Error loading launcher properties: " + e.getMessage());
125       System.exit(8);
126     }
127
128     String companyName = appInfoRoot.getChild("company").getAttributeValue("name");
129     Element names = appInfoRoot.getChild("names");
130     String productShortName = names.getAttributeValue("product");
131     String productFullName = names.getAttributeValue("fullname");
132     Element versionElement = appInfoRoot.getChild("version");
133     int majorVersion = Integer.parseInt(versionElement.getAttributeValue("major"));
134     String minorVersionString = versionElement.getAttributeValue("minor");
135     Pattern p = Pattern.compile("(\\d+)(\\.(\\d+))?");
136     Matcher matcher = p.matcher(minorVersionString);
137     if (!matcher.matches()) {
138       System.err.println("Unexpected minor version format: " + minorVersionString);
139     }
140     int minorVersion = Integer.parseInt(matcher.group(1));
141     int bugfixVersion = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 0;
142     String buildNumber = appInfoRoot.getChild("build").getAttributeValue("number");
143     String versionString = "" + majorVersion + "." + minorVersion + "." + bugfixVersion + "." + buildNumber;
144
145     int year = new GregorianCalendar().get(Calendar.YEAR);
146
147     LauncherGenerator generator = new LauncherGenerator(template, new File(args[4]));
148     try {
149       generator.load();
150
151       for (Map.Entry<Object, Object> pair : properties.entrySet()) {
152         String key = (String) pair.getKey();
153         Integer id = resourceIDs.get(key);
154         if (id == null) {
155           System.err.println("Invalid stringtable ID found: " + key);
156           System.exit(9);
157         }
158         generator.setResourceString(id, (String) pair.getValue());
159       }
160
161       generator.injectBitmap(resourceIDs.get("IDB_SPLASH"), splashBmpStream.toByteArray());
162       generator.injectIcon(resourceIDs.get("IDI_WINLAUNCHER"), iconStream);
163
164       generator.setVersionInfoString("LegalCopyright", "Copyright (C) 2000-" + year + " " + companyName);
165       generator.setVersionInfoString("ProductName", productFullName);
166       generator.setVersionInfoString("FileVersion", versionString);
167       generator.setVersionInfoString("FileDescription", productFullName);
168       generator.setVersionInfoString("ProductVersion", versionString);
169       generator.setVersionInfoString("InternalName", productShortName.toLowerCase() + ".exe");
170       generator.setVersionInfoString("OriginalFilename", productShortName.toLowerCase() + ".exe");
171       generator.setVersionNumber(majorVersion, minorVersion, bugfixVersion);
172
173       generator.generate();
174     } catch (IOException e) {
175       e.printStackTrace();
176       System.exit(10);
177     }
178   }
179
180   private static Map<String, Integer> loadResourceIDs(String arg) throws IOException {
181     Map<String, Integer> result = new HashMap<String, Integer>();
182     BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(arg), Charset.forName("UTF-16")));
183     Pattern pattern = Pattern.compile("#define (\\w+)\\s+(\\d+)");
184     try {
185       while(true) {
186         String line = reader.readLine();
187         if (line == null) break;
188         Matcher m = pattern.matcher(line);
189         if (m.matches()) {
190           result.put(m.group(1), Integer.parseInt(m.group(2)));
191         }
192       }
193     }
194     finally {
195       reader.close();
196     }
197     return result;
198   }
199 }