Source Code Cross Referenced for MIDletStateHandler.java in  » 6.0-JDK-Modules » j2me » com » sun » midp » midlet » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » com.sun.midp.midlet 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *
003:         *
004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006:         * 
007:         * This program is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU General Public License version
009:         * 2 only, as published by the Free Software Foundation.
010:         * 
011:         * This program is distributed in the hope that it will be useful, but
012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014:         * General Public License version 2 for more details (a copy is
015:         * included at /legal/license.txt).
016:         * 
017:         * You should have received a copy of the GNU General Public License
018:         * version 2 along with this work; if not, write to the Free Software
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA
021:         * 
022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023:         * Clara, CA 95054 or visit www.sun.com if you need additional
024:         * information or have any questions.
025:         */
026:
027:        package com.sun.midp.midlet;
028:
029:        import javax.microedition.midlet.MIDlet;
030:        import javax.microedition.midlet.MIDletStateChangeException;
031:
032:        import com.sun.midp.security.Permissions;
033:        import com.sun.midp.security.SecurityToken;
034:
035:        import com.sun.midp.log.Logging;
036:        import com.sun.midp.log.LogChannels;
037:
038:        /**
039:         * The MIDletStateHandler starts and controls MIDlets through the lifecycle
040:         * states.
041:         * MIDlets are created using its no-arg Constructor. Once created
042:         * a MIDlet is sequenced through the <code>ACTIVE</code>,
043:         * <code>PAUSED</code>, and <code>DESTROYED</code> states.
044:         * <p>
045:         * The MIDletStateHandler is a singleton for the suite being run and
046:         * is retrieved with getMIDletStateHandler(). This allow the
047:         * MIDletStateHandler to be the anchor of trust internally for the MIDP API,
048:         * restricted methods can obtain the MIDletStateHandler for a MIDlet suite
049:         * inorder to check the properties and actions of a suite.
050:         * Because of this, there MUST only be one a MIDlet suite per
051:         * MIDletStateHandler. In addition a method can assume that the application
052:         * manager is the caller if there is no suite started.</p>
053:         * <p>
054:         * The MIDlet methods are protected in the javax.microedition.midlet package
055:         * so the MIDletStateHandler can not call them directly.  The MIDletState
056:         * object and
057:         * MIDletTunnel subclass class allow the MIDletStateHandler to hold the state
058:         * of the
059:         * MIDlet and to invoke methods on it.  The MIDletState instance is created
060:         * by the MIDlet when it is constructed.
061:         * <p>
062:         * This implementation of the MIDletStateHandler introduces
063:         * extra internal MIDlet states to allow processing of MIDlet
064:         * requested state changes in the control thread and serialized with
065:         * other state changes.  The additional states are:
066:         * <UL>
067:         * <LI> <code>ACTIVE_PENDING</code> - The MIDlet is still PAUSED but
068:         * will be <code>ACTIVE</code> after startApp is called when the state is
069:         * next processed.
070:         * <LI> <code>PAUSE_PENDING</code> - The MIDlet is still ACTIVE but
071:         * will be <code>PAUSED</code> after pauseApp is called when the state is
072:         * next processed.
073:         * <LI> <code>DESTROY_PENDING</code> - Indicates that the MIDlet needs
074:         * to be <code>DESTROYED</code>. The MIDlet's destroyApp has not yet been
075:         * called.
076:         * </UL>
077:         * The MIDletStateHandler loops, looking for MIDlets that require state changes
078:         * and making the requested changes including calling methods in
079:         * the MIDlet to make the change.
080:         * <p>
081:         * When a MIDlet's state is changed to <code>ACTIVE</code>,
082:         * <code>PAUSED</code>, or <code>DESTROYED</code> the MIDlet state listener
083:         * is notified of the change, which in turn sends the notification onto
084:         * the central AMS.
085:         *
086:         * @see MIDlet
087:         * @see MIDletPeer
088:         * @see MIDletLoader
089:         * @see MIDletStateHandler
090:         */
091:
092:        public class MIDletStateHandler {
093:            /** the current MIDlet suite. */
094:            private MIDletSuite midletSuite;
095:            /** loads the MIDlets from a suite's JAR in a VM specific way. */
096:            private MIDletLoader midletLoader;
097:            /** array of MIDlets. */
098:            private MIDletPeer[] midlets;
099:            /** current number of MIDlets [0..n-1]. */
100:            private int nmidlets;
101:            /**  next index to be scanned by selectForeground. */
102:            private int scanIndex;
103:
104:            /** The event handler of all MIDlets in an Isolate. */
105:            private static MIDletStateHandler stateHandler;
106:            /** The listener for the state of all MIDlets in an Isolate. */
107:            private static MIDletStateListener listener;
108:
109:            /** Serializes the creation of MIDlets. */
110:            private static Object createMIDletLock = new Object();
111:
112:            /** New MIDlet peer waiting for the next MIDlet created to claim it. */
113:            private static MIDletPeer newMidletPeer;
114:
115:            /** MIDlet peer for MIDlet being constructed but not registered yet. */
116:            private MIDletPeer underConstructionPeer;
117:
118:            /**
119:             * Construct a new MIDletStateHandler object.
120:             */
121:            private MIDletStateHandler() {
122:                nmidlets = 0;
123:
124:                // start with 5 empty slots, we will add more if needed
125:                midlets = new MIDletPeer[5];
126:            }
127:
128:            /**
129:             * Gets the MIDletStateHandler that manages the lifecycle states of
130:             * MIDlets running in an Isolate.
131:             * <p>
132:             * If the instance of the MIDletStateHandler has already been created
133:             * it is returned.  If not it is created.
134:             * The instance becomes the MIDletStateHandler for this suite.
135:             * <p>
136:             * The fact that there is one handler per Isolate
137:             * is a security feature. Also a security feature, is that
138:             * getMIDletStateHandler is
139:             * static, so API can find out what suite is calling, if in the future
140:             * multiple suites can be run in the same VM, the MIDlet state handler
141:             * for each suite
142:             * should be loaded in a different classloader or have some other way
143:             * having multiple instances of static class data.
144:             *
145:             * @return the MIDlet state handler for this Isolate
146:             */
147:            public static synchronized MIDletStateHandler getMidletStateHandler() {
148:                /*
149:                 * If the midlet state handler has not been created, create one now.
150:                 */
151:                if (stateHandler == null) {
152:                    /* This is the default scheduler class */
153:                    stateHandler = new MIDletStateHandler();
154:                }
155:
156:                return stateHandler;
157:            }
158:
159:            /**
160:             * Initializes MIDlet State Handler.
161:             *
162:             * @param token security token for initilaization
163:             * @param theMIDletStateListener processes MIDlet states in a
164:             *                               VM specific way
165:             * @param theMidletLoader loads a MIDlet in a VM specific way
166:             * @param thePlatformRequestHandler the platform request handler
167:             */
168:            public void initMIDletStateHandler(SecurityToken token,
169:                    MIDletStateListener theMIDletStateListener,
170:                    MIDletLoader theMidletLoader,
171:                    PlatformRequest thePlatformRequestHandler) {
172:
173:                token.checkIfPermissionAllowed(Permissions.AMS);
174:
175:                listener = theMIDletStateListener;
176:                midletLoader = theMidletLoader;
177:
178:                MIDletPeer.initClass(this , listener, thePlatformRequestHandler);
179:            }
180:
181:            /**
182:             * Starts a MIDlet from outside of the package.
183:             *
184:             * @param classname name of MIDlet class
185:             * @param displayName name to show the user
186:             *
187:             * @exception SecurityException if the suite does not have the
188:             *   AMS permission.
189:             * @exception ClassNotFoundException is thrown, if the MIDlet main class is
190:             * not found
191:             * @exception InstantiationException is thrown, if the MIDlet can not be
192:             * created
193:             * @exception IllegalAccessException is thrown, if the MIDlet is not
194:             * permitted to perform a specific operation
195:             */
196:            public void startMIDlet(String classname, String displayName)
197:                    throws ClassNotFoundException, InstantiationException,
198:                    IllegalAccessException {
199:                startMIDlet(0, classname, displayName);
200:            }
201:
202:            /**
203:             * Starts a MIDlet from outside of the package.
204:             *
205:             * @param externalAppId ID of given by an external application manager
206:             * @param classname name of MIDlet class
207:             * @param displayName name to show the user
208:             *
209:             * @exception SecurityException if the suite does not have the
210:             *   AMS permission.
211:             * @exception ClassNotFoundException is thrown, if the MIDlet main class is
212:             * not found
213:             * @exception InstantiationException is thrown, if the MIDlet can not be
214:             * created
215:             * @exception IllegalAccessException is thrown, if the MIDlet is not
216:             * permitted to perform a specific operation
217:             */
218:            public void startMIDlet(int externalAppId, String classname,
219:                    String displayName) throws ClassNotFoundException,
220:                    InstantiationException, IllegalAccessException {
221:
222:                midletSuite.checkIfPermissionAllowed(Permissions.AMS);
223:                createAndRegisterMIDlet(externalAppId, classname);
224:            }
225:
226:            /**
227:             * Starts a MIDlet from outside of the package.
228:             *
229:             * @param token security token of the caller
230:             * @param classname name of MIDlet class
231:             * @param displayName name to show the user
232:             *
233:             * @exception SecurityException if the caller does not have the
234:             *   AMS permission.
235:             * @exception ClassNotFoundException is thrown, if the MIDlet main class is
236:             * not found
237:             * @exception InstantiationException is thrown, if the MIDlet can not be
238:             * created
239:             * @exception IllegalAccessException is thrown, if the MIDlet is not
240:             * permitted to perform a specific operation
241:             */
242:            public void startMIDlet(SecurityToken token, String classname,
243:                    String displayName) throws ClassNotFoundException,
244:                    InstantiationException, IllegalAccessException {
245:                startMIDlet(token, 0, classname, displayName);
246:            }
247:
248:            /**
249:             * Starts a MIDlet from outside of the package.
250:             *
251:             * @param token security token of the caller
252:             * @param externalAppId ID of given by an external application manager
253:             * @param classname name of MIDlet class
254:             * @param displayName name to show the user
255:             *
256:             * @exception SecurityException if the caller does not have the
257:             *   AMS permission.
258:             * @exception ClassNotFoundException is thrown, if the MIDlet main class is
259:             * not found
260:             * @exception InstantiationException is thrown, if the MIDlet can not be
261:             * created
262:             * @exception IllegalAccessException is thrown, if the MIDlet is not
263:             * permitted to perform a specific operation
264:             */
265:            public void startMIDlet(SecurityToken token, int externalAppId,
266:                    String classname, String displayName)
267:                    throws ClassNotFoundException, InstantiationException,
268:                    IllegalAccessException {
269:
270:                token.checkIfPermissionAllowed(Permissions.AMS);
271:                createAndRegisterMIDlet(externalAppId, classname);
272:            }
273:
274:            /**
275:             * Gets the class name first midlet in the list of running MIDlets.
276:             *
277:             * @return the classname or null if no midlet are running
278:             */
279:            public String getFirstRunningMidlet() {
280:                synchronized (this ) {
281:                    if (nmidlets <= 0) {
282:                        return null;
283:                    }
284:
285:                    return midlets[0].midlet.getClass().getName();
286:                }
287:            }
288:
289:            /**
290:             * Registers a MIDlet being constructed.
291:             *
292:             * @param midlet to be registered with this state handler
293:             */
294:            private void register(MIDlet midlet) {
295:                synchronized (this ) {
296:                    MIDletPeer state = MIDletPeer.getMIDletPeer(midlet);
297:
298:                    /*
299:                     * If a MIDlet of the same class is already running
300:                     * Make the existing MIDlet current so that startSuite()
301:                     * will run it
302:                     */
303:                    int i = findMIDletByClass(state);
304:                    if (i >= 0) {
305:                        state.setState(MIDletPeer.DESTROY_PENDING);
306:                        // Fall into adding it to the list so destroyApp
307:                        // can be called at a reasonable time.
308:                    }
309:
310:                    // Grow the list if necessary
311:                    if (nmidlets >= midlets.length) {
312:                        MIDletPeer[] n = new MIDletPeer[nmidlets + 5];
313:                        System.arraycopy(midlets, 0, n, 0, nmidlets);
314:                        midlets = n;
315:                    }
316:
317:                    // Add it to the end of the list
318:                    midlets[nmidlets++] = state;
319:
320:                    // MIDlet peer is registered now
321:                    underConstructionPeer = null;
322:
323:                    this .notify();
324:                }
325:            }
326:
327:            /**
328:             * Creates and register MIDlet with VM notification
329:             * of the MIDlet's startup phase.
330:             *
331:             * @param externalAppId ID of given by an external application manager
332:             * @param classname name of MIDlet class
333:             *
334:             * @exception ClassNotFoundException if the MIDlet class is
335:             * not found
336:             * @exception InstantiationException if the MIDlet cannot be
337:             * created
338:             * @exception IllegalAccessException if the MIDlet is not
339:             * permitted to perform a specific operation
340:             */
341:            private void createAndRegisterMIDlet(int externalAppId,
342:                    String classname) throws ClassNotFoundException,
343:                    InstantiationException, IllegalAccessException {
344:
345:                listener.midletPreStart(getMIDletSuite(), classname);
346:                register(createMIDlet(externalAppId, classname));
347:            }
348:
349:            /**
350:             * Provides a object with a mechanism to retrieve
351:             * <code>MIDletSuite</code> being run.
352:             *
353:             * @return MIDletSuite being run
354:             */
355:            public MIDletSuite getMIDletSuite() {
356:                return midletSuite;
357:            }
358:
359:            /**
360:             * Runs MIDlets until there are none.
361:             * Handle any pending state transitions of any MIDlet.
362:             * If there are none, wait for transitions.
363:             * If there is no foreground MIDlet select one that is ACTIVE and
364:             * has setCurrent != null.
365:             * <p>
366:             * If the foreground MIDlet changes from the ACTIVE_FOREGROUND state
367:             * it automatically looses the foreground and and new one is selected.
368:             *
369:             * @param exceptionHandler the handler for midlet execution exceptions.
370:             * @param aMidletSuite the current midlet suite
371:             * @param externalAppId ID of given by an external application manager
372:             * @param classname name of MIDlet class
373:             *
374:             * @exception ClassNotFoundException is thrown, if the MIDlet main class is
375:             * not found
376:             * @exception InstantiationException is thrown, if the MIDlet can not be
377:             * created
378:             * @exception IllegalAccessException is thrown, if the MIDlet is not
379:             * permitted to perform a specific operation
380:             */
381:            public void startSuite(
382:                    MIDletSuiteExceptionListener exceptionHandler,
383:                    MIDletSuite aMidletSuite, int externalAppId,
384:                    String classname) throws ClassNotFoundException,
385:                    InstantiationException, IllegalAccessException {
386:
387:                if (midletSuite != null) {
388:                    throw new RuntimeException(
389:                            "There is already a MIDlet Suite running.");
390:
391:                }
392:
393:                midletSuite = aMidletSuite;
394:                createAndRegisterMIDlet(externalAppId, classname);
395:
396:                /*
397:                 * Until there are no MIDlets
398:                 * Scan all the MIDlets looking for state changes.
399:                 */
400:                while (nmidlets > 0) {
401:                    try {
402:                        MIDletPeer curr;
403:                        int state;
404:
405:                        /*
406:                         * A MIDlet can change the MIDlet concurrently.
407:                         * the MIDlet state handler this is used to
408:                         * synchronize these changes. However any calls to outside of
409:                         * this package should NOT be done holding
410:                         * "this".
411:                         * For this reason there are 2 phases each with a switch
412:                         * statement to process a state.
413:                         *
414:                         * The state is obtained and changed before the work is
415:                         * done so that when "this" is released to
416:                         * perform external calls for that state, any state change done
417:                         * by the MIDlet concurrently are not lost.
418:                         */
419:
420:                        synchronized (this ) {
421:                            /*
422:                             * Find the highest priority state of any MIDlet and
423:                             * process, but do not hold the lock while processing
424:                             * to avoid deadlocks with LCDUI and event handling.
425:                             * Perform state changes with a lock so
426:                             * no state changes are lost.
427:                             */
428:                            curr = selectByPriority();
429:                            state = curr.getState();
430:
431:                            switch (state) {
432:                            case MIDletPeer.ACTIVE:
433:                                // fall through
434:                            case MIDletPeer.PAUSED:
435:                                // Wait for some change in the state of a MIDlet
436:                                // that needs attention
437:                                try {
438:                                    this .wait();
439:                                } catch (InterruptedException e) {
440:
441:                                    if (Logging.REPORT_LEVEL <= Logging.WARNING) {
442:                                        Logging.report(Logging.WARNING,
443:                                                LogChannels.LC_AMS,
444:                                                "InterruptedException "
445:                                                        + "during mutex wait");
446:                                    }
447:                                }
448:
449:                                continue;
450:
451:                            case MIDletPeer.ACTIVE_PENDING:
452:                                // Start the MIDlet
453:                                curr.setStateWithoutNotify(MIDletPeer.ACTIVE);
454:                                break;
455:
456:                            case MIDletPeer.PAUSE_PENDING:
457:                                // The system wants the MIDlet paused
458:                                curr.setStateWithoutNotify(MIDletPeer.PAUSED);
459:                                break;
460:
461:                            case MIDletPeer.DESTROY_PENDING:
462:                                curr
463:                                        .setStateWithoutNotify(MIDletPeer.DESTROYED);
464:                                break;
465:
466:                            case MIDletPeer.DESTROYED:
467:                                unregister(curr);
468:                                break;
469:
470:                            default:
471:                                throw new Error("Illegal MIDletPeer state "
472:                                        + curr.getState());
473:                            }
474:                        }
475:
476:                        /** perform work that may block outside of "this" */
477:                        switch (state) {
478:                        case MIDletPeer.ACTIVE_PENDING:
479:                            try {
480:                                listener.preActivated(getMIDletSuite(), curr
481:                                        .getMIDlet().getClass().getName());
482:
483:                                curr.startApp();
484:                            } catch (Throwable ex) {
485:                                if (Logging.TRACE_ENABLED) {
486:                                    Logging.trace(ex,
487:                                            "startApp threw an Exception");
488:                                }
489:                                curr.setState(MIDletPeer.DESTROY_PENDING);
490:                                exceptionHandler.handleException(ex);
491:                                break;
492:                            }
493:
494:                            /*
495:                             * The actual state of the MIDlet is already active.
496:                             * But any notifications done after startApp call.
497:                             */
498:                            listener.midletActivated(getMIDletSuite(), curr
499:                                    .getMIDlet());
500:                            break;
501:
502:                        case MIDletPeer.PAUSE_PENDING:
503:                            try {
504:                                curr.pauseApp();
505:                            } catch (Throwable ex) {
506:                                if (Logging.TRACE_ENABLED) {
507:                                    Logging.trace(ex,
508:                                            "pauseApp threw an Exception");
509:                                }
510:
511:                                curr.setState(MIDletPeer.DESTROY_PENDING);
512:                                exceptionHandler.handleException(ex);
513:                                break;
514:                            }
515:
516:                            /*
517:                             * The actual state of the MIDlet is already paused.
518:                             * But any notifications done after pauseApp() call.
519:                             */
520:                            listener.midletPaused(getMIDletSuite(), curr
521:                                    .getMIDlet().getClass().getName());
522:
523:                            break;
524:
525:                        case MIDletPeer.DESTROY_PENDING:
526:                            // If the MIDlet is in the DESTROY_PENDING state
527:                            // call its destroyApp method to clean it up.
528:                            try {
529:                                // Tell the MIDlet to cleanup.
530:                                curr.destroyApp(true);
531:                            } catch (MIDletStateChangeException ex) {
532:                                if (Logging.REPORT_LEVEL <= Logging.WARNING) {
533:                                    Logging
534:                                            .report(
535:                                                    Logging.WARNING,
536:                                                    LogChannels.LC_AMS,
537:                                                    "destroyApp  threw a "
538:                                                            + "MIDletStateChangeException");
539:                                }
540:                                exceptionHandler.handleException(ex);
541:                            } catch (Throwable ex) {
542:                                if (Logging.TRACE_ENABLED) {
543:                                    Logging.trace(ex,
544:                                            "destroyApp threw an Exception");
545:                                }
546:                                exceptionHandler.handleException(ex);
547:                            }
548:                            break;
549:
550:                        case MIDletPeer.DESTROYED:
551:                            listener.midletDestroyed(getMIDletSuite(), curr
552:                                    .getMIDlet().getClass().getName());
553:                            break;
554:                        }
555:                    } catch (Throwable ex) {
556:                        if (Logging.TRACE_ENABLED) {
557:                            Logging.trace(ex, "Exception in startSuite");
558:                        }
559:                        exceptionHandler.handleException(ex);
560:                    }
561:                }
562:            }
563:
564:            /**
565:             * Destroys all running MIDlets in this suite only. This method is only
566:             * used by the push registry in single VM mode.
567:             */
568:            public void destroySuite() {
569:                synchronized (this ) {
570:                    for (int i = 0; i < nmidlets; i++) {
571:                        if (midlets[i].getState() != MIDletPeer.DESTROYED) {
572:                            midlets[i]
573:                                    .setStateWithoutNotify(MIDletPeer.DESTROY_PENDING);
574:                        }
575:                    }
576:
577:                    this .notify();
578:                }
579:            }
580:
581:            /**
582:             * Checks if the named <code>MIDlet</code> has already been instantiated.
583:             * @param name class name of <code>MIDlet</code> to test if
584:             *             currently run
585:             * @return <code>true</code> if an instance of the MIDlet is already
586:             *     running
587:             */
588:            public boolean isRunning(String name) {
589:                boolean found = false;
590:                synchronized (this ) {
591:                    if (underConstructionPeer != null
592:                            && underConstructionPeer.getMIDlet().getClass()
593:                                    .getName().equals(name)) {
594:                        found = true;
595:                    } else {
596:                        for (int i = 0; i < nmidlets; i++) {
597:                            if (midlets[i].getMIDlet().getClass().getName()
598:                                    .equals(name)) {
599:                                // found only if has not been destroyed
600:                                found = (midlets[i].getState() != MIDletPeer.DESTROYED);
601:                                break;
602:                            }
603:                        }
604:                    }
605:                }
606:                return found;
607:            }
608:
609:            /**
610:             * Gets MIDlet event consumer of the named <code>MIDlet</code>.
611:             *
612:             * @param token security token for authorizing the caller
613:             * @param name class name of <code>MIDlet</code>
614:             *
615:             * @return reference of the MIDlet event consumer
616:             */
617:            public MIDletEventConsumer getMIDletEventConsumer(
618:                    SecurityToken token, String name) {
619:                token.checkIfPermissionAllowed(Permissions.AMS);
620:
621:                synchronized (this ) {
622:                    for (int i = 0; i < nmidlets; i++) {
623:                        if (midlets[i].getMIDlet().getClass().getName().equals(
624:                                name)) {
625:                            return midlets[i];
626:                        }
627:                    }
628:                }
629:
630:                return null;
631:            }
632:
633:            /**
634:             * Looks through the current MIDlets and select one to
635:             * be processed.
636:             * <p>Note: that this method is called while synchronized on "this"
637:             * @return the MIDlet to process next
638:             */
639:            private MIDletPeer selectByPriority() {
640:                MIDletPeer found = null; // Chosen MIDletPeer
641:                int state = -1; // the state of the chosen MIDlet
642:
643:                /*
644:                 * Find the most desirable MIDlet based on its state
645:                 * The higher state values are preferred because they
646:                 * are needed for cleanup.
647:                 */
648:                for (int i = nmidlets - 1; i >= 0; i--) {
649:
650:                    // make sure index is inside current array, favoring the end
651:                    if (scanIndex < 0 || scanIndex >= nmidlets)
652:                        scanIndex = nmidlets - 1;
653:
654:                    // Pick this MIDlet if the state is higher priority
655:                    int s = midlets[scanIndex].getState();
656:                    if (s > state) {
657:                        found = midlets[scanIndex];
658:                        state = s;
659:                    }
660:                    scanIndex--;
661:                }
662:                return found;
663:            }
664:
665:            /**
666:             * Removes a MIDlet from the list if it is there,
667:             * otherwise ignore the request.
668:             * Call only while synchronized on "this".
669:             * @param m the MIDlet to remove
670:             */
671:            private void unregister(MIDletPeer m) {
672:                // Find it in the list and switch the last one for it.
673:                for (int i = 0; i < nmidlets; i++) {
674:                    if (m == midlets[i]) {
675:                        // Switch the last MIDlet into that offset.
676:                        midlets[i] = midlets[nmidlets - 1];
677:
678:                        // null out from array and remove from map to allow for GC
679:                        midlets[--nmidlets] = null;
680:                        break;
681:                    }
682:                }
683:            }
684:
685:            /**
686:             * Finds a MIDlet in the list by it class.
687:             * Only a single MIDlet of a class can be active at
688:             * a time.
689:             * Must be called synchronized on "this".
690:             * @param m the MIDlet to find
691:             * @return the index in the array of MIDlets.
692:             *  return -1 if the MIDlet is not found.
693:             */
694:            private int findMIDletByClass(MIDletPeer m) {
695:                // Find it in the list
696:                for (int i = 0; i < nmidlets; i++) {
697:                    if (m.getMIDlet().getClass() == midlets[i].getMIDlet()
698:                            .getClass()) {
699:                        return i;
700:                    }
701:                }
702:                return -1;
703:            }
704:
705:            /**
706:             * Creates a MIDlet.
707:             *
708:             * @param externalAppId ID of given by an external application manager
709:             * @param classname name of MIDlet class
710:             *
711:             * @return newly created MIDlet
712:             *
713:             * @exception ClassNotFoundException if the MIDlet class is
714:             * not found
715:             * @exception InstantiationException if the MIDlet cannot be
716:             * created
717:             * @exception IllegalAccessException if the MIDlet is not
718:             * permitted to perform a specific operation
719:             */
720:            private MIDlet createMIDlet(int externalAppId, String classname)
721:                    throws ClassNotFoundException, InstantiationException,
722:                    IllegalAccessException {
723:                MIDlet midlet = null;
724:
725:                synchronized (createMIDletLock) {
726:                    /*
727:                     * Just in case there is a hole we have not found.
728:                     * Make sure there is not a new MIDlet state already created.
729:                     */
730:                    if (newMidletPeer != null) {
731:                        throw new SecurityException("Recusive MIDlet creation");
732:                    }
733:
734:                    newMidletPeer = new MIDletPeer();
735:                    underConstructionPeer = newMidletPeer;
736:                    try {
737:                        /*
738:                         * We can send a MIDlet create event because the peer that
739:                         * the AMS uses has been created.
740:                         */
741:                        listener.midletCreated(getMIDletSuite(), classname,
742:                                externalAppId);
743:
744:                        try {
745:                            midlet = midletLoader.newInstance(getMIDletSuite(),
746:                                    classname);
747:                            return midlet;
748:                        } finally {
749:                            if (midlet == null) {
750:                                /*
751:                                 * The MIDlet was not constructed, send destroy
752:                                 * notification to remove the peer from any lists.
753:                                 */
754:                                listener.midletDestroyed(getMIDletSuite(),
755:                                        classname);
756:                            }
757:                        }
758:                    } finally {
759:                        /* Make sure the creation window is closed. */
760:                        newMidletPeer = null;
761:                    }
762:                }
763:            }
764:
765:            /**
766:             * Called by the MIDlet constructor to a new MIDletPeer object.
767:             *
768:             * @param token security token for authorizing the caller
769:             * @param m the MIDlet for which this state is being created;
770:             *          must not be <code>null</code>.
771:             * @return the preallocated MIDletPeer for the MIDlet being constructed by
772:             *         {@link #createMIDlet}
773:             *
774:             * @exception SecurityException AMS permission is not granted and
775:             * if is constructor is not being called in the context of
776:             * <code>createMIDlet</code>.
777:             */
778:            public static MIDletPeer newMIDletPeer(SecurityToken token, MIDlet m) {
779:                token.checkIfPermissionAllowed(Permissions.MIDP);
780:
781:                synchronized (createMIDletLock) {
782:                    MIDletPeer temp;
783:
784:                    if (newMidletPeer == null) {
785:                        throw new SecurityException(
786:                                "MIDlet not constructed by createMIDlet.");
787:                    }
788:
789:                    temp = newMidletPeer;
790:                    newMidletPeer = null;
791:                    temp.midlet = m;
792:                    return temp;
793:                }
794:            }
795:
796:            /**
797:             * Retrieves current state of the MIDlet given.
798:             * @param midlet the MIDlet of interest
799:             * @return the MIDlet state as defined in MIDletPeer class
800:             */
801:            public static int getMIDletState(MIDlet midlet) {
802:                return MIDletPeer.getMIDletPeer(midlet).getState();
803:            }
804:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.