Source Code Cross Referenced for ConnectionController.java in  » 6.0-JDK-Modules » j2me » com » sun » midp » jump » push » executive » 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.jump.push.executive 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
004:         * 
005:         * This program is free software; you can redistribute it and/or
006:         * modify it under the terms of the GNU General Public License version
007:         * 2 only, as published by the Free Software Foundation.
008:         * 
009:         * This program is distributed in the hope that it will be useful, but
010:         * WITHOUT ANY WARRANTY; without even the implied warranty of
011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012:         * General Public License version 2 for more details (a copy is
013:         * included at /legal/license.txt).
014:         * 
015:         * You should have received a copy of the GNU General Public License
016:         * version 2 along with this work; if not, write to the Free Software
017:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
018:         * 02110-1301 USA
019:         * 
020:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
021:         * Clara, CA 95054 or visit www.sun.com if you need additional
022:         * information or have any questions.
023:         */
024:
025:        package com.sun.midp.jump.push.executive;
026:
027:        import com.sun.midp.push.gcf.ConnectionReservation;
028:        import com.sun.midp.push.gcf.DataAvailableListener;
029:        import com.sun.midp.push.gcf.ReservationDescriptor;
030:        import com.sun.midp.jump.push.executive.persistence.Store;
031:        import com.sun.midp.push.gcf.PermissionCallback;
032:        import com.sun.midp.push.gcf.ReservationDescriptorFactory;
033:        import java.io.IOException;
034:        import java.util.Collection;
035:        import java.util.HashMap;
036:        import java.util.HashSet;
037:        import java.util.Iterator;
038:        import java.util.Set;
039:        import java.util.Vector;
040:        import javax.microedition.io.ConnectionNotFoundException;
041:
042:        /** Push connection controller. */
043:        final class ConnectionController {
044:            /** Store to save connection info. */
045:            private final Store store;
046:
047:            /**
048:             * Reservation descriptor factory.
049:             *
050:             * IMPL_NOTE: hopefully will go away
051:             */
052:            private final ReservationDescriptorFactory reservationDescriptorFactory;
053:
054:            /** Lifecycle adapter implementation. */
055:            private final LifecycleAdapter lifecycleAdapter;
056:
057:            /** Current reservations. */
058:            private final Reservations reservations;
059:
060:            /**
061:             * Creates an instance.
062:             *
063:             * @param store persistent store to save connection info into
064:             * (cannot be <code>null</code>)
065:             *
066:             * @param reservationDescriptorFactory reservation descriptor factory
067:             * (cannot be <code>null</code>
068:             *
069:             * @param lifecycleAdapter adapter to launch <code>MIDlet</code>
070:             * (cannot be <code>null</code>)
071:             */
072:            public ConnectionController(
073:                    final Store store,
074:                    final ReservationDescriptorFactory reservationDescriptorFactory,
075:                    final LifecycleAdapter lifecycleAdapter) {
076:                this .store = store;
077:                this .reservationDescriptorFactory = reservationDescriptorFactory;
078:                this .lifecycleAdapter = lifecycleAdapter;
079:                this .reservations = new Reservations();
080:
081:                reserveConnectionsFromStore();
082:            }
083:
084:            /**
085:             * Registers the connection.
086:             *
087:             * <p>
088:             * Saves the connection into persistent store and reserves it
089:             * for <code>MIDlet</code>.
090:             * </p>
091:             *
092:             * <p>
093:             * The connection should be already preverified (see
094:             * <code>reservationDescriptor</code> parameter) and all the security
095:             * checks should be performed.
096:             * </p>
097:             *
098:             * @param midletSuiteID <code>MIDlet</code> suite ID
099:             *
100:             * @param midlet <code>MIDlet</code> class name
101:             * (cannot be <code>null</code>)
102:             *
103:             * @param reservationDescriptor reservation descriptor
104:             * (cannot be <code>null</code>)
105:             *
106:             * @throws IOException if the connection is already registered or
107:             * if there are insufficient resources to handle the registration request
108:             */
109:            public synchronized void registerConnection(
110:                    final int midletSuiteID, final String midlet,
111:                    final ReservationDescriptor reservationDescriptor)
112:                    throws IOException {
113:                final String connectionName = reservationDescriptor
114:                        .getConnectionName();
115:
116:                /*
117:                 * IMPL_NOTE: due to ReservationDescriptor#reserve limitations,
118:                 * need to unregister registered connection first
119:                 */
120:                final ReservationHandler previous = reservations
121:                        .queryByConnectionName(connectionName);
122:                if (previous != null) {
123:                    if (previous.getSuiteId() != midletSuiteID) {
124:                        // Already registered for another suite, fail quickly
125:                        throw new IOException("registered for another suite");
126:                    }
127:                    removeRegistration(previous);
128:                }
129:
130:                final ReservationHandler reservationHandler = new ReservationHandler(
131:                        midletSuiteID, midlet, reservationDescriptor);
132:
133:                final String filter = reservationDescriptor.getFilter();
134:
135:                try {
136:                    // TODO: rethink if we need filter in JUMPConnectionInfo
137:                    final JUMPConnectionInfo connectionInfo = new JUMPConnectionInfo(
138:                            connectionName, midlet, filter);
139:                    store.addConnection(midletSuiteID, connectionInfo);
140:                } catch (IOException ioex) {
141:                    reservationHandler.cancel();
142:                    throw ioex; // rethrow IOException
143:                }
144:
145:                reservations.add(reservationHandler);
146:            }
147:
148:            /**
149:             * Unregisters the connection.
150:             *
151:             * <p>
152:             * Removes the connection from persistent store and cancels connection
153:             * reservation.
154:             * </p>
155:             *
156:             * @param midletSuiteID <code>MIDlet</code> suite ID
157:             *
158:             * @param connectionName connection to unregister
159:             * (cannot be <code>null</code>)
160:             *
161:             * @return <code>true</code> if the unregistration was successful,
162:             * <code>false</code> if the connection was not registered
163:             *
164:             * @throws SecurityException if the connection was registered by
165:             * another <code>MIDlet</code>  suite
166:             */
167:            public synchronized boolean unregisterConnection(
168:                    final int midletSuiteID, final String connectionName)
169:                    throws SecurityException {
170:                final ReservationHandler reservationHandler = reservations
171:                        .queryByConnectionName(connectionName);
172:
173:                if (reservationHandler == null) {
174:                    // Connection hasn't been registered
175:                    return false;
176:                }
177:
178:                if (reservationHandler.getSuiteId() != midletSuiteID) {
179:                    throw new SecurityException(
180:                            "attempt to unregister connection of another suite");
181:                }
182:
183:                try {
184:                    removeRegistration(reservationHandler);
185:                } catch (IOException ioex) {
186:                    return false;
187:                }
188:
189:                return true;
190:            }
191:
192:            /**
193:             * Transactionally removes the registration.
194:             *
195:             * @param reservationHandler reservation handler.
196:             *
197:             * @throws IOException if persistent store fails
198:             */
199:            private void removeRegistration(
200:                    final ReservationHandler reservationHandler)
201:                    throws IOException {
202:                final JUMPConnectionInfo info = new JUMPConnectionInfo(
203:                        reservationHandler.getConnectionName(),
204:                        reservationHandler.getMidlet(), reservationHandler
205:                                .getFilter());
206:                store.removeConnection(reservationHandler.getSuiteId(), info);
207:                reservationHandler.cancel();
208:                reservations.remove(reservationHandler);
209:            }
210:
211:            /**
212:             * Returns a list of registered connections for <code>MIDlet</code> suite.
213:             *
214:             * @param midletSuiteID <code>MIDlet</code> suite ID
215:             *
216:             * @param available if <code>true</code>, only return
217:             * the list of connections with input available, otherwise
218:             * return the complete list of registered connections for
219:             * <code>MIDlet</code> suite
220:             *
221:             * @return array of registered connection strings, where each connection
222:             * is represented by the generic connection <em>protocol</em>,
223:             * <em>host</em> and <em>port</em> number identification
224:             */
225:            public synchronized String[] listConnections(
226:                    final int midletSuiteID, final boolean available) {
227:                final Vector result = new Vector();
228:
229:                final Iterator it = reservations.queryBySuiteID(midletSuiteID)
230:                        .iterator();
231:                while (it.hasNext()) {
232:                    final ReservationHandler handler = (ReservationHandler) it
233:                            .next();
234:                    if ((!available) || handler.hasAvailableData()) {
235:                        result.add(handler.getConnectionName());
236:                    }
237:                }
238:                return (String[]) result.toArray(new String[result.size()]);
239:            }
240:
241:            /**
242:             * Fetches the <code>MIDlet</code> by the connection.
243:             *
244:             * @param midletSuiteID <code>MIDlet</code> suite ID to query for
245:             *
246:             * @param connectionName connectionName as passed into
247:             * {@link #registerConnection}
248:             * (cannot be <code>null</code>)
249:             *
250:             * @return <code>MIDlet</code> associated with <code>connectionName</code>
251:             * or <code>null</code> if there is no appropriate association
252:             */
253:            public synchronized String getMIDlet(final int midletSuiteID,
254:                    final String connectionName) {
255:                final ReservationHandler reservationHandler = reservations
256:                        .queryByConnectionName(connectionName);
257:
258:                if ((reservationHandler == null)
259:                        || (reservationHandler.getSuiteId() != midletSuiteID)) {
260:                    return null;
261:                }
262:
263:                return reservationHandler.getMidlet();
264:            }
265:
266:            /**
267:             * Fetches the filter by the connection.
268:             *
269:             * @param midletSuiteID <code>MIDlet</code> suite ID to query for
270:             *
271:             * @param connectionName connectionName as passed into
272:             * {@link #registerConnection}
273:             * (cannot be <code>null</code>)
274:             *
275:             * @return filter associated with <code>connectionName</code> or
276:             * <code>null</code> if there is no appropriate association
277:             */
278:            public synchronized String getFilter(final int midletSuiteID,
279:                    final String connectionName) {
280:                final ReservationHandler reservationHandler = reservations
281:                        .queryByConnectionName(connectionName);
282:
283:                if ((reservationHandler == null)
284:                        || (reservationHandler.getSuiteId() != midletSuiteID)) {
285:                    return null;
286:                }
287:
288:                return reservationHandler.getFilter();
289:            }
290:
291:            /**
292:             * Removes connections for the given suite.
293:             *
294:             * <p>
295:             * NOTE: <code>midletSuiteID</code> must refer to valid installed
296:             *  <code>MIDlet</code> suite.  However, it might refer to the
297:             *  suite without connections.
298:             * </p>
299:             *
300:             * @param midletSuiteID ID of the suite to remove connections for
301:             */
302:            public synchronized void removeSuiteConnections(
303:                    final int midletSuiteID) {
304:                /*
305:                 * IMPL_NOTE: one shouldn't remove and iterate in same time.
306:                 * The solution is to copy first.  It's safe for method is synchronized.
307:                 */
308:                final Collection rs = reservations
309:                        .queryBySuiteID(midletSuiteID);
310:                final ReservationHandler[] handlers = new ReservationHandler[rs
311:                        .size()];
312:                rs.toArray(handlers);
313:                for (int i = 0; i < handlers.length; i++) {
314:                    try {
315:                        removeRegistration(handlers[i]);
316:                    } catch (IOException ioex) {
317:                        logError("failed to remove " + handlers[i] + ": "
318:                                + ioex);
319:                    }
320:                }
321:            }
322:
323:            /**
324:             * Disposes a connection controller.
325:             *
326:             * <p>
327:             * Cancels all the reservations and callbacks.
328:             * </p>
329:             *
330:             * <p>
331:             * The only thing one MUST do with disposed
332:             * <code>ConnectionController</code> is to garbage-collect it.
333:             * </p>
334:             */
335:            public synchronized void dispose() {
336:                for (Iterator it = reservations.getAllReservations().iterator(); it
337:                        .hasNext();) {
338:                    final ReservationHandler rh = (ReservationHandler) it
339:                            .next();
340:                    rh.cancel();
341:                }
342:                reservations.clear();
343:            }
344:
345:            /**
346:             * Noop permission callback for startup connection reservation.
347:             *
348:             * IMPL_NOTE: hopefully will go away when we'll get rid of
349:             * reservationDescriptorFactory
350:             */
351:            private final PermissionCallback noopPermissionCallback = new PermissionCallback() {
352:                public void checkForPermission(final String permissionName,
353:                        final String resource, final String extraValue)
354:                        throws SecurityException {
355:                }
356:            };
357:
358:            /**
359:             * Reads and reserves connections in persistent store.
360:             */
361:            private void reserveConnectionsFromStore() {
362:                /*
363:                 * IMPL_NOTE: currently connection info is stored as plain data.
364:                 * However, as reservation descriptors should be serializable
365:                 * for jump, it might be a good idea to store descriptors
366:                 * directly and thus get rid of reservation factory in
367:                 * ConnectionController altogether.
368:                 */
369:                store.listConnections(new Store.ConnectionsConsumer() {
370:                    public void consume(final int suiteId,
371:                            final JUMPConnectionInfo[] connections) {
372:                        for (int i = 0; i < connections.length; i++) {
373:                            final JUMPConnectionInfo info = connections[i];
374:                            try {
375:                                registerConnection(suiteId, info.midlet,
376:                                        reservationDescriptorFactory
377:                                                .getDescriptor(info.connection,
378:                                                        info.filter,
379:                                                        noopPermissionCallback));
380:                            } catch (ConnectionNotFoundException cnfe) {
381:                                logError("failed to register " + info + ": "
382:                                        + cnfe);
383:                            } catch (IOException ioex) {
384:                                logError("failed to register " + info + ": "
385:                                        + ioex);
386:                            }
387:                        }
388:                    }
389:                });
390:            }
391:
392:            /**
393:             * Reservation listening handler.
394:             *
395:             * <p>
396:             * IMPL_NOTE: invariant is: one instance of a handler per registration
397:             * and thus default Object <code>equals</code> and <code>hashCode</code>
398:             * should be enough
399:             * </p>
400:             *
401:             * <p>
402:             * TODO: think if common code with AlarmRegistry.AlarmTask can be factored
403:             * </p>
404:             */
405:            final class ReservationHandler implements  DataAvailableListener {
406:                /** Reservation's app. */
407:                private final MIDPApp midpApp;
408:
409:                /** Connection name. */
410:                private final String connectionName;
411:
412:                /** Connection filter. */
413:                private final String filter;
414:
415:                /** Connection reservation. */
416:                private final ConnectionReservation connectionReservation;
417:
418:                /** Cancelation status. */
419:                private boolean cancelled = false;
420:
421:                /**
422:                 * Creates a handler and reserves the connection.
423:                 *
424:                 * @param midletSuiteID <code>MIDlet</code> suite ID of reservation
425:                 *
426:                 * @param midlet <code>MIDlet</code> suite ID of reservation.
427:                 * (cannot be <code>null</code>)
428:                 *
429:                 * @param reservationDescriptor reservation descriptor
430:                 * (cannot be <code>null</code>)
431:                 *
432:                 * @throws IOException if reservation fails
433:                 */
434:                ReservationHandler(final int midletSuiteID,
435:                        final String midlet,
436:                        final ReservationDescriptor reservationDescriptor)
437:                        throws IOException {
438:                    this .midpApp = new MIDPApp(midletSuiteID, midlet);
439:
440:                    this .connectionName = reservationDescriptor
441:                            .getConnectionName();
442:                    this .filter = reservationDescriptor.getFilter();
443:
444:                    this .connectionReservation = reservationDescriptor.reserve(
445:                            midletSuiteID, midlet, this );
446:                }
447:
448:                /**
449:                 * Gets <code>MIDlet</code> suite ID.
450:                 *
451:                 * @return <code>MIDlet</code> suite ID
452:                 */
453:                int getSuiteId() {
454:                    return midpApp.midletSuiteID;
455:                }
456:
457:                /**
458:                 * Gets <code>MIDlet</code> class name.
459:                 *
460:                 * @return <code>MIDlet</code> class name
461:                 */
462:                String getMidlet() {
463:                    return midpApp.midlet;
464:                }
465:
466:                /**
467:                 * Gets connection name.
468:                 *
469:                 * @return connection name
470:                 */
471:                String getConnectionName() {
472:                    return connectionName;
473:                }
474:
475:                /**
476:                 * Gets connection filter.
477:                 *
478:                 * @return connection filter
479:                 */
480:                String getFilter() {
481:                    return filter;
482:                }
483:
484:                /**
485:                 * Cancels reservation.
486:                 */
487:                void cancel() {
488:                    cancelled = true;
489:                    connectionReservation.cancel();
490:                }
491:
492:                /**
493:                 * See {@link ConnectionReservation#hasAvailableData}.
494:                 *
495:                 * @return <code>true</code> iff reservation has available data
496:                 */
497:                boolean hasAvailableData() {
498:                    return connectionReservation.hasAvailableData();
499:                }
500:
501:                /** {@inheritDoc} */
502:                public void dataAvailable() {
503:                    synchronized (ConnectionController.this ) {
504:                        if (cancelled) {
505:                            return;
506:                        }
507:
508:                        try {
509:                            lifecycleAdapter.launchMidlet(
510:                                    midpApp.midletSuiteID, midpApp.midlet);
511:                        } catch (Exception ex) {
512:                            /* IMPL_NOTE: need to handle _all_ the exceptions. */
513:                            /* TBD: uncomment when logging can be disabled
514:                             * (not to interfer with unittests)
515:                            logError(
516:                                    "Failed to launch \"" + midpApp.midlet + "\"" +
517:                                    " (suite ID: " + midpApp.midletSuiteID + "): " +
518:                                    ex);
519:                             */
520:                        }
521:                    }
522:                }
523:            }
524:
525:            /** Internal structure that manages needed mappings. */
526:            static final class Reservations {
527:                /** Mappings from connection to reservations. */
528:                private final HashMap connection2data = new HashMap();
529:
530:                /** Mappings from suite id to set of reservations. */
531:                private final HashMap suiteId2data = new HashMap();
532:
533:                /**
534:                 * Adds a reservation into reservations.
535:                 *
536:                 * @param reservationHandler reservation to add
537:                 */
538:                void add(final ReservationHandler reservationHandler) {
539:                    connection2data.put(reservationHandler.getConnectionName(),
540:                            reservationHandler);
541:
542:                    final Set data = getData(reservationHandler.getSuiteId());
543:                    if (data != null) {
544:                        data.add(reservationHandler);
545:                    } else {
546:                        final Set d = new HashSet();
547:                        d.add(reservationHandler);
548:                        suiteId2data.put(new Integer(reservationHandler
549:                                .getSuiteId()), d);
550:                    }
551:                }
552:
553:                /**
554:                 * Removes a reservation from reservations.
555:                 *
556:                 * @param reservationHandler reservation to remove
557:                 */
558:                void remove(final ReservationHandler reservationHandler) {
559:                    connection2data.remove(reservationHandler
560:                            .getConnectionName());
561:
562:                    getData(reservationHandler.getSuiteId()).remove(
563:                            reservationHandler);
564:                }
565:
566:                /**
567:                 * Queries the reservations by the connection.
568:                 *
569:                 * @param connectionName name of connection to query by
570:                 * (cannot be <code>null</code>)
571:                 *
572:                 * @return reservation (<code>null</code> if absent)
573:                 */
574:                ReservationHandler queryByConnectionName(
575:                        final String connectionName) {
576:                    return (ReservationHandler) connection2data
577:                            .get(connectionName);
578:                }
579:
580:                /**
581:                 * Queries the reservations by the suite id.
582:                 *
583:                 * @param midletSuiteID <code>MIDlet</code> suite ID to query by
584:                 * @return collection of <code>ReservationHandler</code>s
585:                 * (cannot be <code>null</code>)
586:                 */
587:                Collection queryBySuiteID(final int midletSuiteID) {
588:                    final Set data = getData(midletSuiteID);
589:                    return (data == null) ? new HashSet() : data;
590:                }
591:
592:                /**
593:                 * Gets all the reservations.
594:                 *
595:                 * @return collection of reservations
596:                 */
597:                Collection getAllReservations() {
598:                    return connection2data.values();
599:                }
600:
601:                /**
602:                 * Clears all the reservations.
603:                 */
604:                void clear() {
605:                    connection2data.clear();
606:                    suiteId2data.clear();
607:                }
608:
609:                /**
610:                 * Gets reservation set by suite id.
611:                 *
612:                 * @param midletSuiteID <code>MIDlet</code> suite ID
613:                 *
614:                 * @return set of reservations or <code>null</code> if absent
615:                 */
616:                private Set getData(final int midletSuiteID) {
617:                    return (Set) suiteId2data.get(new Integer(midletSuiteID));
618:                }
619:            }
620:
621:            /**
622:             * Logs error message.
623:             *
624:             * <p>
625:             * TBD: common logging
626:             * </p>
627:             *
628:             * @param message message to log
629:             */
630:            private static void logError(final String message) {
631:                System.err.println("ERROR ["
632:                        + ConnectionController.class.getName() + "]: "
633:                        + message);
634:            }
635:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.