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