1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.microemu.app.util;
29
30 import java.io.ByteArrayInputStream;
31 import java.io.File;
32 import java.io.FileOutputStream;
33 import java.io.FileWriter;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.net.URL;
37 import java.util.ArrayList;
38 import java.util.Enumeration;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.jar.JarEntry;
42 import java.util.jar.JarFile;
43 import java.util.jar.JarInputStream;
44 import java.util.jar.JarOutputStream;
45 import java.util.jar.Manifest;
46
47 import org.microemu.DisplayComponent;
48 import org.microemu.EmulatorContext;
49 import org.microemu.MIDletBridge;
50 import org.microemu.app.classloader.ClassPreprocessor;
51 import org.microemu.app.classloader.ExtensionsClassLoader;
52 import org.microemu.app.classloader.InstrumentationConfig;
53 import org.microemu.app.ui.Message;
54 import org.microemu.app.ui.noui.NoUiDisplayComponent;
55 import org.microemu.device.DeviceDisplay;
56 import org.microemu.device.FontManager;
57 import org.microemu.device.InputMethod;
58 import org.microemu.device.impl.DeviceDisplayImpl;
59 import org.microemu.device.impl.DeviceImpl;
60 import org.microemu.device.j2se.J2SEDevice;
61 import org.microemu.device.j2se.J2SEDeviceDisplay;
62 import org.microemu.device.j2se.J2SEFontManager;
63 import org.microemu.device.j2se.J2SEInputMethod;
64 import org.microemu.log.Logger;
65
66 public class AppletProducer {
67
68 public static void createHtml(File htmlOutputFile, DeviceImpl device, String className, File midletOutputFile,
69 File appletPackageOutputFile, File deviceOutputFile) throws IOException {
70 int width;
71 int height;
72 if (((DeviceDisplayImpl) device.getDeviceDisplay()).isResizable()) {
73 width = device.getDeviceDisplay().getFullWidth();
74 height = device.getDeviceDisplay().getFullHeight();
75 } else {
76 width = device.getNormalImage().getWidth();
77 height = device.getNormalImage().getHeight();
78 }
79
80 FileWriter writer = null;
81 try {
82 writer = new FileWriter(htmlOutputFile);
83 writer.write("");
84 writer.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n\n");
85 writer.write("<html>\n");
86 writer.write("\t<head>\n");
87 writer.write("\t\t<title>MicroEmulator</title>\n");
88 writer.write("\t</head>\n");
89 writer.write("\t<body>\n");
90 writer.write("\t\t<applet code=\"org.microemu.applet.Main\"\n");
91 writer.write("\t\t\t\twidth=\"" + width + "\" height=\"" + height + "\"\n");
92 writer.write("\t\t\t\tarchive=\"" + appletPackageOutputFile.getName() + ",");
93 if (deviceOutputFile != null) {
94 writer.write(deviceOutputFile.getName() + ",");
95 }
96 writer.write(midletOutputFile.getName() + "\">\n");
97 writer.write("\t\t\t<param name=\"midlet\" value=\"" + className + "\">\n");
98 if (device.getDescriptorLocation() != null) {
99 writer.write("\t\t\t<param name=\"device\" value=\"" + device.getDescriptorLocation() + "\">\n");
100 }
101 writer.write("\t\t</applet>\n");
102 writer.write("\t</body>\n");
103 writer.write("</html>\n");
104 } finally {
105 IOUtils.closeQuietly(writer);
106 }
107 }
108
109 public static void createMidlet(URL midletInputUrl, File midletOutputFile) throws IOException {
110 JarInputStream jis = null;
111 JarInputStream ijis = null;
112 JarOutputStream jos = null;
113 InstrumentationConfig config = new InstrumentationConfig();
114 config.setEnhanceThreadCreation(true);
115 try {
116 jis = new JarInputStream(midletInputUrl.openStream());
117 Manifest manifest = jis.getManifest();
118 if (manifest == null) {
119 jos = new JarOutputStream(new FileOutputStream(midletOutputFile));
120 } else {
121 jos = new JarOutputStream(new FileOutputStream(midletOutputFile), manifest);
122 }
123
124 byte[] inputBuffer = new byte[1024];
125 JarEntry jarEntry;
126 while ((jarEntry = jis.getNextJarEntry()) != null) {
127 if (jarEntry.isDirectory() == false) {
128 String name = jarEntry.getName();
129 int size = 0;
130 int read;
131 int length = inputBuffer.length;
132 while ((read = jis.read(inputBuffer, size, length)) > 0) {
133 size += read;
134
135 length = 1024;
136 if (size + length > inputBuffer.length) {
137 byte[] newInputBuffer = new byte[size + length];
138 System.arraycopy(inputBuffer, 0, newInputBuffer, 0, inputBuffer.length);
139 inputBuffer = newInputBuffer;
140 }
141 }
142
143 byte[] outputBuffer = inputBuffer;
144 int outputSize = size;
145 if (name.endsWith(".class")) {
146 outputBuffer = ClassPreprocessor.instrument(new ByteArrayInputStream(inputBuffer, 0, size), config);
147 outputSize = outputBuffer.length;
148 }
149 jos.putNextEntry(new JarEntry(name));
150 jos.write(outputBuffer, 0, outputSize);
151 }
152 }
153
154 URL url = AppletProducer.class.getResource("/microemu-injected.jar");
155 if (url != null) {
156 ijis = new JarInputStream(url.openStream());
157 while ((jarEntry = ijis.getNextJarEntry()) != null) {
158 if (jarEntry.getName().equals("org/microemu/Injected.class")) {
159 jos.putNextEntry(new JarEntry(jarEntry.getName()));
160 int read;
161 while ((read = ijis.read(inputBuffer)) > 0) {
162 jos.write(inputBuffer, 0, read);
163 }
164 }
165 }
166 } else {
167 Logger.error("Cannot find microemu-injected.jar resource in classpath");
168 }
169 } finally {
170 IOUtils.closeQuietly(jis);
171 IOUtils.closeQuietly(ijis);
172 IOUtils.closeQuietly(jos);
173 }
174 }
175
176
177 public static void main(String args[]) {
178 String midletClass = null;;
179 File appletInputFile = null;
180 File deviceInputFile = null;
181 File midletInputFile = null;
182 File htmlOutputFile = null;
183 File appletOutputFile = null;
184 File deviceOutputFile = null;
185 File midletOutputFile = null;
186
187 List params = new ArrayList();
188 for (int i = 0; i < args.length; i++) {
189 params.add(args[i]);
190 }
191
192 Iterator argsIterator = params.iterator();
193 while (argsIterator.hasNext()) {
194 String arg = (String) argsIterator.next();
195 argsIterator.remove();
196
197 if ((arg.equals("--help")) || (arg.equals("-help"))) {
198 System.out.println(usage());
199 System.exit(0);
200 } else if (arg.equals("--midletClass")) {
201 midletClass = (String) argsIterator.next();
202 argsIterator.remove();
203 } else if (arg.equals("--appletInput")) {
204 appletInputFile = new File((String) argsIterator.next());
205 argsIterator.remove();
206 } else if (arg.equals("--deviceInput")) {
207 deviceInputFile = new File((String) argsIterator.next());
208 argsIterator.remove();
209 } else if (arg.equals("--midletInput")) {
210 midletInputFile = new File((String) argsIterator.next());
211 argsIterator.remove();
212 } else if (arg.equals("--htmlOutput")) {
213 htmlOutputFile = new File((String) argsIterator.next());
214 argsIterator.remove();
215 } else if (arg.equals("--appletOutput")) {
216 appletOutputFile = new File((String) argsIterator.next());
217 argsIterator.remove();
218 } else if (arg.equals("--deviceOutput")) {
219 deviceOutputFile = new File((String) argsIterator.next());
220 argsIterator.remove();
221 } else if (arg.equals("--midletOutput")) {
222 midletOutputFile = new File((String) argsIterator.next());
223 argsIterator.remove();
224 }
225 }
226
227 if (midletClass == null
228 || appletInputFile == null
229 || deviceInputFile == null
230 || midletInputFile == null
231 || htmlOutputFile == null
232 || appletOutputFile == null
233 || deviceOutputFile == null
234 || midletOutputFile == null) {
235 System.out.println(usage());
236 System.exit(0);
237 }
238
239 try {
240 DeviceImpl device = null;
241 String descriptorLocation = null;
242 JarFile jar = new JarFile(deviceInputFile);
243 for (Enumeration en = jar.entries(); en.hasMoreElements();) {
244 String entry = ((JarEntry) en.nextElement()).getName();
245 if ((entry.toLowerCase().endsWith(".xml") || entry.toLowerCase().endsWith("device.txt"))
246 && !entry.toLowerCase().startsWith("meta-inf")) {
247 descriptorLocation = entry;
248 break;
249 }
250 }
251 if (descriptorLocation != null) {
252 EmulatorContext context = new EmulatorContext() {
253 private DisplayComponent displayComponent = new NoUiDisplayComponent();
254
255 private InputMethod inputMethod = new J2SEInputMethod();
256
257 private DeviceDisplay deviceDisplay = new J2SEDeviceDisplay(this);
258
259 private FontManager fontManager = new J2SEFontManager();
260
261 public DisplayComponent getDisplayComponent() {
262 return displayComponent;
263 }
264
265 public InputMethod getDeviceInputMethod() {
266 return inputMethod;
267 }
268
269 public DeviceDisplay getDeviceDisplay() {
270 return deviceDisplay;
271 }
272
273 public FontManager getDeviceFontManager() {
274 return fontManager;
275 }
276
277 public InputStream getResourceAsStream(String name) {
278 return MIDletBridge.getCurrentMIDlet().getClass().getResourceAsStream(name);
279 }
280
281 public boolean platformRequest(final String URL) {
282 new Thread(new Runnable() {
283 public void run() {
284 Message.info("MIDlet requests that the device handle the following URL: " + URL);
285 }
286 }).start();
287
288 return false;
289 }
290 };
291
292 URL[] urls = new URL[1];
293 urls[0] = deviceInputFile.toURI().toURL();
294 ClassLoader classLoader = new ExtensionsClassLoader(urls, urls.getClass().getClassLoader());
295 device = DeviceImpl.create(context, classLoader, descriptorLocation, J2SEDevice.class);
296 }
297
298 if (device == null) {
299 System.out.println("Error parsing device package: " + descriptorLocation);
300 System.exit(0);
301 }
302
303 createHtml(htmlOutputFile, device, midletClass, midletOutputFile, appletOutputFile, deviceOutputFile);
304 createMidlet(midletInputFile.toURI().toURL(), midletOutputFile);
305 IOUtils.copyFile(appletInputFile, appletOutputFile);
306 IOUtils.copyFile(deviceInputFile, deviceOutputFile);
307 } catch (IOException ex) {
308 ex.printStackTrace();
309 }
310
311 System.exit(0);
312 }
313
314
315 private static String usage() {
316 return "--midletClass {midlet class name} \n" +
317 "--appletInput {emulator applet jar input file} \n" +
318 "--deviceInput {device jar input file} \n" +
319 "--midletInput {midlet jar input file} \n" +
320 "--htmlOutput {html output file} \n" +
321 "--appletOutput {emulator applet jar output file} \n" +
322 "--deviceOutput {device jar output file} \n" +
323 "--midletOutput {midlet jar output file}";
324 }
325
326 }