1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.microemu.app;
22
23 import java.io.File;
24 import java.io.FileNotFoundException;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.Serializable;
28 import java.lang.reflect.Constructor;
29 import java.lang.reflect.InvocationTargetException;
30 import java.lang.reflect.Method;
31 import java.lang.reflect.Modifier;
32 import java.net.MalformedURLException;
33 import java.net.URL;
34 import java.net.URLConnection;
35 import java.util.Enumeration;
36 import java.util.HashMap;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.Map;
41 import java.util.Vector;
42 import java.util.jar.JarEntry;
43 import java.util.jar.JarInputStream;
44 import java.util.zip.ZipException;
45
46 import javax.microedition.midlet.MIDlet;
47 import javax.microedition.midlet.MIDletStateChangeException;
48
49 import org.microemu.EmulatorContext;
50 import org.microemu.Injected;
51 import org.microemu.MIDletAccess;
52 import org.microemu.MIDletBridge;
53 import org.microemu.MIDletContext;
54 import org.microemu.MIDletEntry;
55 import org.microemu.MicroEmulator;
56 import org.microemu.RecordStoreManager;
57 import org.microemu.app.classloader.ExtensionsClassLoader;
58 import org.microemu.app.classloader.MIDletClassLoader;
59 import org.microemu.app.classloader.MIDletClassLoaderConfig;
60 import org.microemu.app.launcher.Launcher;
61 import org.microemu.app.ui.Message;
62 import org.microemu.app.ui.ResponseInterfaceListener;
63 import org.microemu.app.ui.StatusBarListener;
64 import org.microemu.app.util.DeviceEntry;
65 import org.microemu.app.util.FileRecordStoreManager;
66 import org.microemu.app.util.IOUtils;
67 import org.microemu.app.util.MIDletResourceLoader;
68 import org.microemu.app.util.MIDletSystemProperties;
69 import org.microemu.app.util.MIDletThread;
70 import org.microemu.app.util.MIDletTimer;
71 import org.microemu.app.util.MidletURLReference;
72 import org.microemu.device.Device;
73 import org.microemu.device.DeviceFactory;
74 import org.microemu.device.impl.DeviceImpl;
75 import org.microemu.log.Logger;
76 import org.microemu.microedition.ImplFactory;
77 import org.microemu.microedition.ImplementationInitialization;
78 import org.microemu.microedition.io.ConnectorImpl;
79 import org.microemu.util.Base64Coder;
80 import org.microemu.util.JadMidletEntry;
81 import org.microemu.util.JadProperties;
82 import org.microemu.util.MemoryRecordStoreManager;
83
84 public class Common implements MicroEmulator, CommonInterface {
85
86 protected EmulatorContext emulatorContext;
87
88 protected JadProperties jad = new JadProperties();
89
90 private static Common instance;
91
92 private static Launcher launcher;
93
94 private static StatusBarListener statusBarListener = null;
95
96 private JadProperties manifest = new JadProperties();
97
98 private RecordStoreManager recordStoreManager;
99
100 private ResponseInterfaceListener responseInterfaceListener = null;
101
102 private ExtensionsClassLoader extensionsClassLoader;
103
104 private Vector extensions = new Vector();
105
106 private MIDletClassLoaderConfig mIDletClassLoaderConfig;
107
108 private boolean useSystemClassLoader = false;
109
110 private boolean autoTests = false;
111
112 private String propertiesJad = null;
113
114 private String midletClassOrJad = null;
115
116 private String jadURL = null;
117
118 private Object destroyNotify = new Object();
119
120 public Common(EmulatorContext context) {
121 instance = this;
122 this.emulatorContext = context;
123
124 try {
125 launcher = new Launcher(this);
126 launcher.setCurrentMIDlet(launcher);
127 } finally {
128 MIDletBridge.setThreadMIDletContext(null);
129 }
130
131
132
133
134
135 ImplFactory.instance();
136 MIDletSystemProperties.initContext();
137
138 ImplFactory.registerGCF(ImplFactory.DEFAULT, new ConnectorImpl());
139
140 MIDletBridge.setMicroEmulator(this);
141 }
142
143 public RecordStoreManager getRecordStoreManager() {
144 return recordStoreManager;
145 }
146
147 public void setRecordStoreManager(RecordStoreManager manager) {
148 this.recordStoreManager = manager;
149 }
150
151 public String getAppProperty(String key) {
152 if (key.equals("microedition.platform")) {
153 return "MicroEmulator";
154 } else if (key.equals("microedition.profiles")) {
155 return "MIDP-2.0";
156 } else if (key.equals("microedition.configuration")) {
157 return "CLDC-1.0";
158 } else if (key.equals("microedition.locale")) {
159 return Locale.getDefault().getLanguage();
160 } else if (key.equals("microedition.encoding")) {
161 return System.getProperty("file.encoding");
162 }
163
164 String result = jad.getProperty(key);
165 if (result == null) {
166 result = manifest.getProperty(key);
167 }
168
169 return result;
170 }
171
172 public InputStream getResourceAsStream(String name) {
173 return emulatorContext.getResourceAsStream(name);
174 }
175
176 public void notifyDestroyed(MIDletContext midletContext) {
177 Logger.debug("notifyDestroyed");
178 notifyImplementationMIDletDestroyed();
179 startLauncher(midletContext);
180 }
181
182 public void destroyMIDletContext(MIDletContext midletContext) {
183 if ((midletContext != null) && (MIDletBridge.getMIDletContext() == midletContext)
184 && !midletContext.isLauncher()) {
185 Logger.debug("destroyMIDletContext");
186 }
187 MIDletThread.contextDestroyed(midletContext);
188 synchronized (destroyNotify) {
189 destroyNotify.notifyAll();
190 }
191 }
192
193 public Launcher getLauncher() {
194 return launcher;
195 }
196
197 public static void dispose() {
198 try {
199 MIDletAccess midletAccess = MIDletBridge.getMIDletAccess();
200 if (midletAccess != null) {
201 midletAccess.destroyApp(true);
202 }
203 } catch (MIDletStateChangeException ex) {
204 Logger.error(ex);
205 }
206
207 DeviceFactory.getDevice().getInputMethod().dispose();
208 }
209
210 public static boolean isJadExtension(String nameString) {
211 if (nameString == null) {
212 return false;
213 }
214 int end = nameString.lastIndexOf('.');
215 if (end == -1) {
216 return false;
217 }
218 return nameString.substring(end + 1, nameString.length()).toLowerCase(Locale.ENGLISH).equals("jad");
219 }
220
221
222
223
224 public static void openJadUrlSafe(String urlString) {
225 try {
226 getInstance().openJadUrl(urlString);
227 } catch (IOException e) {
228 Message.error("Unable to open jad " + urlString, e);
229 }
230 }
231
232 protected void openJadUrl(String urlString) throws IOException {
233 midletClassOrJad = urlString;
234 if (!autoTests) {
235 openJadUrl(urlString, createMIDletClassLoader());
236 } else {
237 runAutoTests(urlString, false);
238 }
239 }
240
241 private void runAutoTests(final String urlString, final boolean exitAtTheEnd) {
242 final Common common = getInstance();
243 Thread t = new Thread("AutoTestsThread") {
244 public void run() {
245 boolean firstJad = true;
246 do {
247 common.jad.clear();
248 Logger.debug("AutoTests open jad", urlString);
249 try {
250 common.jad = loadJadProperties(urlString);
251 } catch (IOException e) {
252 if (firstJad) {
253 Logger.debug(e);
254 } else {
255 Logger.debug("AutoTests no more tests");
256 }
257 break;
258 }
259 firstJad = false;
260
261 JadMidletEntry jadMidletEntry;
262 Iterator it = common.jad.getMidletEntries().iterator();
263 if (!it.hasNext()) {
264 Message.error("MIDlet Suite has no entries");
265 break;
266 }
267 jadMidletEntry = (JadMidletEntry) it.next();
268 String midletClassName = jadMidletEntry.getClassName();
269
270 boolean firstJar = true;
271 do {
272 MIDletClassLoader midletClassLoader = createMIDletClassLoader();
273 String tmpURL = saveJar2TmpFile(urlString, firstJar);
274 if (tmpURL == null) {
275 Logger.debug("AutoTests no new jar");
276 break;
277 }
278 firstJar = false;
279 Class midletClass;
280 try {
281 loadJar(urlString, tmpURL, midletClassLoader);
282 midletClass = midletClassLoader.loadClass(midletClassName);
283 } catch (ClassNotFoundException e) {
284 Logger.debug(e);
285 break;
286 }
287 Logger.debug("AutoTests start class", midletClassName);
288 MIDletContext context = startMidlet(midletClass, MIDletBridge.getMIDletAccess());
289
290 if (MIDletBridge.getMIDletContext() == context) {
291 synchronized (destroyNotify) {
292 try {
293 destroyNotify.wait();
294 } catch (InterruptedException e) {
295 return;
296 }
297 }
298 }
299 while (MIDletThread.hasRunningThreads(context)) {
300 try {
301 Thread.sleep(100);
302 } catch (InterruptedException e) {
303 break;
304 }
305 }
306 Logger.debug("AutoTests ends");
307 } while (true);
308
309 } while (true);
310
311 if (exitAtTheEnd) {
312 System.exit(0);
313 }
314 }
315 };
316
317 t.start();
318 }
319
320 protected String saveJar2TmpFile(String jarUrl, boolean reportError) {
321 InputStream is = null;
322 try {
323 URL url = new URL(jad.getJarURL());
324 URLConnection conn = url.openConnection();
325 is = conn.getInputStream();
326 File tmp = File.createTempFile("me2-", ".jar");
327 tmp.deleteOnExit();
328 IOUtils.copyToFile(is, tmp);
329 return IOUtils.getCanonicalFileClassLoaderURL(tmp);
330 } catch (IOException e) {
331 if (reportError) {
332 Message.error("Unable to open jar " + jarUrl, e);
333 }
334 return null;
335 } finally {
336 IOUtils.closeQuietly(is);
337 }
338 }
339
340 private void openJadUrl(String urlString, MIDletClassLoader midletClassLoader) throws IOException {
341 try {
342 Logger.debug("openJad", urlString);
343 setStatusBar("Loading...");
344 jad.clear();
345 jad = loadJadProperties(urlString);
346
347 loadJar(urlString, jad.getJarURL(), midletClassLoader);
348
349 Config.getUrlsMRU().push(new MidletURLReference(jad.getSuiteName(), urlString));
350 } catch (MalformedURLException ex) {
351 throw ex;
352 } catch (ClassNotFoundException ex) {
353 Logger.error(ex);
354 throw new IOException(ex.getMessage());
355 } catch (FileNotFoundException ex) {
356 Message.error("File Not found", urlString, ex);
357 } catch (NullPointerException ex) {
358 Logger.error("Cannot open jad", urlString, ex);
359 } catch (IllegalArgumentException ex) {
360 Logger.error("Cannot open jad", urlString, ex);
361 }
362 }
363
364 private MIDletContext startMidlet(Class midletClass, MIDletAccess previousMidletAccess) {
365 try {
366 if (previousMidletAccess != null) {
367 previousMidletAccess.destroyApp(true);
368 }
369 } catch (Throwable e) {
370 Message.error("Unable to destroy MIDlet, " + Message.getCauseMessage(e), e);
371 }
372
373 MIDletContext context = new MIDletContext();
374 MIDletBridge.setThreadMIDletContext(context);
375 try {
376 MIDlet m;
377
378 final String errorTitle = "Error starting MIDlet";
379
380 try {
381 Object object = midletClass.newInstance();
382 if (!(object instanceof MIDlet)) {
383 Message.error(errorTitle, "Class " + midletClass.getName() + " should extend MIDlet");
384 return null;
385 }
386 m = (MIDlet) object;
387 } catch (Throwable e) {
388 Message.error(errorTitle, "Unable to create MIDlet, " + Message.getCauseMessage(e), e);
389 MIDletBridge.destroyMIDletContext(context);
390 return null;
391 }
392
393 try {
394 if (context.getMIDlet() != m) {
395 throw new Error("MIDlet Context corrupted");
396 }
397 context.getMIDletAccess().startApp();
398
399 launcher.setCurrentMIDlet(m);
400 notifyImplementationMIDletStart();
401 return context;
402 } catch (Throwable e) {
403 Message.error(errorTitle, "Unable to start MIDlet, " + Message.getCauseMessage(e), e);
404 MIDletBridge.destroyMIDletContext(context);
405 return null;
406 }
407
408 } finally {
409 MIDletBridge.setThreadMIDletContext(null);
410 }
411
412 }
413
414 protected void startLauncher(MIDletContext midletContext) {
415 if ((midletContext != null) && (midletContext.isLauncher())) {
416 return;
417 }
418 if (midletContext != null) {
419 try {
420 MIDletAccess previousMidletAccess = midletContext.getMIDletAccess();
421 if (previousMidletAccess != null) {
422 previousMidletAccess.destroyApp(true);
423 }
424 } catch (Throwable e) {
425 Logger.error("destroyApp error", e);
426 }
427 }
428
429 try {
430 launcher = new Launcher(this);
431 MIDletBridge.getMIDletAccess(launcher).startApp();
432 launcher.setCurrentMIDlet(launcher);
433 } catch (Throwable e) {
434 Message.error("Unable to start launcher MIDlet, " + Message.getCauseMessage(e), e);
435 handleStartMidletException(e);
436 } finally {
437 MIDletBridge.setThreadMIDletContext(null);
438 }
439 }
440
441 public void setStatusBarListener(StatusBarListener listener) {
442 statusBarListener = listener;
443 }
444
445 public boolean platformRequest(String URL) {
446 return false;
447 }
448
449 public void setResponseInterfaceListener(ResponseInterfaceListener listener) {
450 responseInterfaceListener = listener;
451 }
452
453 protected void handleStartMidletException(Throwable e) {
454
455 }
456
457
458
459
460 protected boolean describeJarProblem(URL jarUrl, MIDletClassLoader midletClassLoader) {
461 InputStream is = null;
462 JarInputStream jis = null;
463 try {
464 final String message = "Unable to open jar " + jarUrl;
465 URLConnection conn;
466 try {
467 conn = jarUrl.openConnection();
468 } catch (IOException e) {
469 Message.error(message, e);
470 return true;
471 }
472 try {
473 is = conn.getInputStream();
474 } catch (FileNotFoundException e) {
475 Message.error("The system cannot find the jar file " + jarUrl, e);
476 return true;
477 } catch (IOException e) {
478 Message.error(message, e);
479 return true;
480 }
481 try {
482 jis = new JarInputStream(is);
483 } catch (IOException e) {
484 Message.error(message, e);
485 return true;
486 }
487 try {
488 JarEntry entry = jis.getNextJarEntry();
489 if (entry == null) {
490 Message.error("Empty jar " + jarUrl);
491 return true;
492 }
493
494 while (jis.getNextJarEntry() != null)
495 ;
496 } catch (ZipException e) {
497 Message.error("Problem reading jar " + jarUrl, e);
498 return true;
499 } catch (IOException e) {
500 Message.error("Problem reading jar " + jarUrl, e);
501 return true;
502 }
503
504 return false;
505 } finally {
506 IOUtils.closeQuietly(jis);
507 IOUtils.closeQuietly(is);
508 }
509 }
510
511 protected void loadJar(String jadUrl, String jarUrl, MIDletClassLoader midletClassLoader)
512 throws ClassNotFoundException {
513 if (jarUrl == null) {
514 throw new ClassNotFoundException("Cannot find MIDlet-Jar-URL property in jad");
515 }
516 Logger.debug("openJar", jarUrl);
517
518
519 dispose();
520
521 MIDletBridge.clear();
522
523 setResponseInterface(false);
524 try {
525 URL url = null;
526 try {
527 url = new URL(jarUrl);
528 } catch (MalformedURLException ex) {
529 try {
530 url = new URL(jadUrl.substring(0, jadUrl.lastIndexOf('/') + 1) + jarUrl);
531
532 jad.setCorrectedJarURL(url.toExternalForm());
533 Logger.debug("openJar url", url);
534 } catch (MalformedURLException ex1) {
535 Logger.error("Unable to find jar url", ex1);
536 setResponseInterface(true);
537 }
538 }
539
540 midletClassLoader.addURL(url);
541
542 Launcher.removeMIDletEntries();
543
544 manifest.clear();
545 InputStream is = null;
546 try {
547 is = midletClassLoader.getResourceAsStream("META-INF/MANIFEST.MF");
548 if (is == null) {
549 if (!describeJarProblem(url, midletClassLoader)) {
550 Message.error("Unable to find MANIFEST in MIDlet jar");
551 }
552 return;
553 }
554 manifest.load(is);
555 } catch (IOException e) {
556 Message.error("Unable to read MANIFEST", e);
557 } finally {
558 IOUtils.closeQuietly(is);
559 }
560
561 Launcher.setSuiteName(jad.getSuiteName());
562
563 for (Enumeration e = jad.getMidletEntries().elements(); e.hasMoreElements();) {
564 JadMidletEntry jadEntry = (JadMidletEntry) e.nextElement();
565 Class midletClass = midletClassLoader.loadClass(jadEntry.getClassName());
566 Launcher.addMIDletEntry(new MIDletEntry(jadEntry.getName(), midletClass));
567 }
568 startLauncher(MIDletBridge.getMIDletContext());
569 setStatusBar("");
570 } finally {
571 setResponseInterface(true);
572 }
573 }
574
575 public Device getDevice() {
576 return DeviceFactory.getDevice();
577 }
578
579 public void setDevice(Device device) {
580 MIDletSystemProperties.setDevice(device);
581 DeviceFactory.setDevice(device);
582 }
583
584 private static Common getInstance() {
585 return instance;
586 }
587
588 public static void setStatusBar(String text) {
589 if (statusBarListener != null) {
590 statusBarListener.statusBarChanged(text);
591 }
592 }
593
594 private void setResponseInterface(boolean state) {
595 if (responseInterfaceListener != null) {
596 responseInterfaceListener.stateChanged(state);
597 }
598 }
599
600 private void registerImplementation(String implClassName, Map properties, boolean notFoundError) {
601 final String errorText = "Implementation initialization";
602 try {
603 Class implClass = getExtensionsClassLoader().loadClass(implClassName);
604 if (ImplementationInitialization.class.isAssignableFrom(implClass)) {
605 Object inst = implClass.newInstance();
606 Map parameters = new HashMap();
607 parameters.put(ImplementationInitialization.PARAM_EMULATOR_ID, Config.getEmulatorID());
608 if (properties != null) {
609 parameters.putAll(properties);
610 } else {
611 Map extensions = Config.getExtensions();
612 Map prop = (Map)extensions.get(implClassName);
613 if (prop != null) {
614 parameters.putAll(prop);
615 }
616 }
617 ((ImplementationInitialization) inst).registerImplementation(parameters);
618 Logger.debug("implementation registered", implClassName);
619 extensions.add(inst);
620 } else {
621 Logger.debug("initialize implementation", implClassName);
622 boolean isStatic = true;
623 try {
624
625 Constructor c = implClass.getConstructor(null);
626 if (Modifier.isPublic(c.getModifiers())) {
627 isStatic = false;
628 implClass.newInstance();
629 }
630 } catch (NoSuchMethodException e) {
631 }
632
633 if (isStatic) {
634 try {
635 Method getinst = implClass.getMethod("instance", null);
636 if (Modifier.isStatic(getinst.getModifiers())) {
637 getinst.invoke(implClass, null);
638 } else {
639 Logger.debug("No known way to initialize implementation class");
640 }
641 } catch (NoSuchMethodException e) {
642 Logger.debug("No known way to initialize implementation class");
643 } catch (InvocationTargetException e) {
644 Logger.debug("Unable to initialize Implementation", e.getCause());
645 }
646 }
647 }
648 } catch (ClassNotFoundException e) {
649 if (notFoundError) {
650 Logger.error(errorText, e);
651 } else {
652 Logger.warn(errorText + " " + e);
653 }
654 } catch (InstantiationException e) {
655 Logger.error(errorText, e);
656 } catch (IllegalAccessException e) {
657 Logger.error(errorText, e);
658 }
659 }
660
661 public void loadImplementationsFromConfig() {
662 Map extensions = Config.getExtensions();
663 for (Iterator iterator = extensions.entrySet().iterator(); iterator.hasNext();) {
664 Map.Entry entry = (Map.Entry) iterator.next();
665 registerImplementation((String) entry.getKey(), (Map) entry.getValue(), false);
666 }
667 }
668
669 public void notifyImplementationMIDletStart() {
670 for (Iterator iterator = extensions.iterator(); iterator.hasNext();) {
671 ImplementationInitialization impl = (ImplementationInitialization) iterator.next();
672 impl.notifyMIDletStart();
673 }
674 }
675
676 public void notifyImplementationMIDletDestroyed() {
677 for (Iterator iterator = extensions.iterator(); iterator.hasNext();) {
678 ImplementationInitialization impl = (ImplementationInitialization) iterator.next();
679 impl.notifyMIDletDestroyed();
680 }
681 }
682
683 public void initParams(List params, DeviceEntry defaultDevice, Class defaultDeviceClass) {
684 MIDletClassLoaderConfig clConfig = new MIDletClassLoaderConfig();
685 Class deviceClass = null;
686 String deviceDescriptorLocation = null;
687 RecordStoreManager paramRecordStoreManager = null;
688
689 Iterator argsIterator = params.iterator();
690
691 try {
692 while (argsIterator.hasNext()) {
693 String arg = (String) argsIterator.next();
694 argsIterator.remove();
695
696 if ((arg.equals("--help")) || (arg.equals("-help"))) {
697 System.out.println(usage());
698 System.exit(0);
699 } else if (arg.equals("--id")) {
700 Config.setEmulatorID((String) argsIterator.next());
701 argsIterator.remove();
702 } else if ((arg.equals("--appclasspath")) || (arg.equals("-appclasspath")) || (arg.equals("-appcp"))) {
703 if (clConfig == null) {
704 throw new ConfigurationException("Wrong command line argument order");
705 }
706 clConfig.addAppClassPath((String) argsIterator.next());
707 argsIterator.remove();
708 } else if (arg.equals("--appclass")) {
709 if (clConfig == null) {
710 throw new ConfigurationException("Wrong command line argument order");
711 }
712 clConfig.addAppClass((String) argsIterator.next());
713 argsIterator.remove();
714 } else if (arg.startsWith("-Xautotest:")) {
715 autoTests = true;
716 jadURL = arg.substring("-Xautotest:".length());
717 } else if (arg.equals("-Xautotest")) {
718 autoTests = true;
719 } else if (arg.equals("--propertiesjad")) {
720 File file = new File((String) argsIterator.next());
721 argsIterator.remove();
722 propertiesJad = file.exists() ? IOUtils.getCanonicalFileURL(file) : arg;
723 } else if (arg.equals("--appclassloader")) {
724 if (clConfig == null) {
725 Message.error("Error", "Wrong command line argument order");
726 break;
727 }
728 clConfig.setDelegationType((String) argsIterator.next());
729 argsIterator.remove();
730 } else if (arg.equals("--usesystemclassloader")) {
731 useSystemClassLoader = true;
732 clConfig.setDelegationType("system");
733 } else if (arg.equals("-d") || arg.equals("--device")) {
734 if (argsIterator.hasNext()) {
735 String tmpDevice = (String) argsIterator.next();
736 argsIterator.remove();
737 if (!tmpDevice.toLowerCase().endsWith(".xml")) {
738 try {
739 deviceClass = Class.forName(tmpDevice);
740 } catch (ClassNotFoundException ex) {
741 }
742 }
743 if (deviceClass == null) {
744 deviceDescriptorLocation = tmpDevice;
745 }
746 }
747 } else if (arg.equals("--rms")) {
748 if (argsIterator.hasNext()) {
749 String tmpRms = (String) argsIterator.next();
750 argsIterator.remove();
751 if (tmpRms.equals("file")) {
752 paramRecordStoreManager = new FileRecordStoreManager();
753 } else if (tmpRms.equals("memory")) {
754 paramRecordStoreManager = new MemoryRecordStoreManager();
755 }
756 }
757 } else if ((arg.equals("--classpath")) || (arg.equals("-classpath")) || (arg.equals("-cp"))) {
758 getExtensionsClassLoader().addClasspath((String) argsIterator.next());
759 argsIterator.remove();
760 } else if (arg.equals("--impl")) {
761 registerImplementation((String) argsIterator.next(), null, true);
762 argsIterator.remove();
763 } else {
764 midletClassOrJad = arg;
765 }
766 }
767 } catch (ConfigurationException e) {
768 Message.error("Error", e.getMessage(), e);
769 return;
770 }
771
772 mIDletClassLoaderConfig = clConfig;
773
774
775
776 ClassLoader classLoader = getExtensionsClassLoader();
777 if (deviceDescriptorLocation != null) {
778 try {
779 setDevice(DeviceImpl.create(emulatorContext, classLoader, deviceDescriptorLocation, defaultDeviceClass));
780 } catch (IOException ex) {
781 Logger.error(ex);
782 }
783 }
784 if (DeviceFactory.getDevice() == null) {
785 try {
786 if (deviceClass == null) {
787 if (defaultDevice.getFileName() != null) {
788 URL[] urls = new URL[1];
789 urls[0] = new File(Config.getConfigPath(), defaultDevice.getFileName()).toURI().toURL();
790 classLoader = createExtensionsClassLoader(urls);
791 }
792 setDevice(DeviceImpl.create(emulatorContext, classLoader, defaultDevice.getDescriptorLocation(),
793 defaultDeviceClass));
794 } else {
795 DeviceImpl device = (DeviceImpl) deviceClass.newInstance();
796 device.init(emulatorContext);
797 setDevice(device);
798 }
799 } catch (InstantiationException ex) {
800 Logger.error(ex);
801 } catch (IllegalAccessException ex) {
802 Logger.error(ex);
803 } catch (IOException ex) {
804 Logger.error(ex);
805 }
806 }
807
808 if (getRecordStoreManager() == null) {
809 if (paramRecordStoreManager == null) {
810 String className = Config.getRecordStoreManagerClassName();
811 if (className != null) {
812 try {
813 Class clazz = Class.forName(className);
814 setRecordStoreManager((RecordStoreManager) clazz.newInstance());
815 } catch (ClassNotFoundException ex) {
816 Logger.error(ex);
817 } catch (InstantiationException ex) {
818 Logger.error(ex);
819 } catch (IllegalAccessException ex) {
820 Logger.error(ex);
821 }
822 }
823 if (getRecordStoreManager() == null) {
824 setRecordStoreManager(new FileRecordStoreManager());
825 }
826 } else {
827 setRecordStoreManager(paramRecordStoreManager);
828 }
829 }
830 }
831
832 private static ExtensionsClassLoader getExtensionsClassLoader() {
833 if (instance.extensionsClassLoader == null) {
834 instance.extensionsClassLoader = new ExtensionsClassLoader(new URL[] {}, instance.getClass()
835 .getClassLoader());
836 }
837 return instance.extensionsClassLoader;
838 }
839
840 private MIDletClassLoader createMIDletClassLoader() {
841 MIDletClassLoader mcl = new MIDletClassLoader(getExtensionsClassLoader());
842 if (!Serializable.class.isAssignableFrom(Injected.class)) {
843 Logger
844 .error("classpath configuration error, Wrong Injected class detected. microemu-injected module should be after microemu-javase in eclipse");
845 }
846 if (mIDletClassLoaderConfig != null) {
847 try {
848 mcl.configure(mIDletClassLoaderConfig);
849 } catch (MalformedURLException e) {
850 Message.error("Error", "Unable to find MIDlet classes, " + Message.getCauseMessage(e), e);
851 }
852 }
853 mcl.disableClassPreporcessing(Injected.class);
854 mcl.disableClassPreporcessing(MIDletThread.class);
855 mcl.disableClassPreporcessing(MIDletTimer.class);
856 MIDletResourceLoader.classLoader = mcl;
857 return mcl;
858 }
859
860 public static ClassLoader createExtensionsClassLoader(final URL[] urls) {
861 return new ExtensionsClassLoader(urls, getExtensionsClassLoader());
862 }
863
864 private static JadProperties loadJadProperties(String urlString) throws IOException {
865 JadProperties properties = new JadProperties();
866
867 URL url = new URL(urlString);
868 if (url.getUserInfo() == null) {
869 properties.load(url.openStream());
870 } else {
871 URLConnection cn = url.openConnection();
872 String userInfo = new String(Base64Coder.encode(url.getUserInfo().getBytes("UTF-8")));
873 cn.setRequestProperty("Authorization", "Basic " + userInfo);
874 properties.load(cn.getInputStream());
875 }
876
877 return properties;
878 }
879
880 public void initMIDlet(boolean startMidlet) {
881 Class midletClass = null;
882
883 if (midletClassOrJad != null && midletClassOrJad.endsWith(".jad")) {
884 try {
885 File file = new File(midletClassOrJad);
886 String url = file.exists() ? IOUtils.getCanonicalFileURL(file) : midletClassOrJad;
887 openJadUrl(url);
888 } catch (IOException exception) {
889 Logger.error("Cannot load " + midletClassOrJad + " URL", exception);
890 }
891 } else if (midletClassOrJad != null) {
892 useSystemClassLoader = mIDletClassLoaderConfig.isClassLoaderDisabled();
893 if (!useSystemClassLoader) {
894 MIDletClassLoader classLoader = createMIDletClassLoader();
895 try {
896 classLoader.addClassURL(midletClassOrJad);
897 midletClass = classLoader.loadClass(midletClassOrJad);
898 } catch (MalformedURLException e) {
899 Message.error("Error", "Unable to find MIDlet class, " + Message.getCauseMessage(e), e);
900 return;
901 } catch (ClassNotFoundException e) {
902 Message.error("Error", "Unable to find MIDlet class, " + Message.getCauseMessage(e), e);
903 return;
904 }
905 } else {
906 try {
907 midletClass = instance.getClass().getClassLoader().loadClass(midletClassOrJad);
908 } catch (ClassNotFoundException e) {
909 Message.error("Error", "Unable to find MIDlet class, " + Message.getCauseMessage(e), e);
910 return;
911 }
912 }
913 }
914
915 if (autoTests) {
916 if (jadURL != null) {
917 runAutoTests(jadURL, true);
918 }
919 } else {
920
921 if (midletClass != null && propertiesJad != null) {
922 try {
923 jad = loadJadProperties(propertiesJad);
924 } catch (IOException e) {
925 Logger.error("Cannot load " + propertiesJad + " URL", e);
926 }
927 }
928
929 boolean started = false;
930
931 if (midletClass == null) {
932 MIDletEntry entry = launcher.getSelectedMidletEntry();
933 if (startMidlet && entry != null) {
934 started = (null != startMidlet(entry.getMIDletClass(), MIDletBridge.getMIDletAccess()));
935 }
936 } else {
937 started = (null != startMidlet(midletClass, MIDletBridge.getMIDletAccess()));
938 }
939 if (!started) {
940 startLauncher(MIDletBridge.getMIDletContext());
941 }
942 }
943
944 }
945
946 public static String usage() {
947 return "[(-d | --device) ({device descriptor} | {device class name}) ] \n" + "[--rms (file | memory)] \n"
948 + "[--id EmulatorID ] \n" + "[--impl {JSR implementation class name}]\n"
949 + "[(--classpath|-cp) <JSR CLASSPATH>]\n" + "[(--appclasspath|--appcp) <MIDlet CLASSPATH>]\n"
950 + "[--appclass <library class name>]\n" + "[--appclassloader strict|delegating|system] \n"
951 + "[-Xautotest:<JAD file url>\n"
952 + "(({MIDlet class name} [--propertiesjad {jad file location}]) | {jad file location})";
953 }
954
955 }