Source Code Cross Referenced for Protocol.java in  » 6.0-JDK-Modules » j2me » com » sun » midp » io » j2me » mms » 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.io.j2me.mms 
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.io.j2me.mms;
028:
029:        import com.sun.midp.io.j2me.ProtocolBase;
030:
031:        import com.sun.midp.io.j2me.sms.MessageObject;
032:
033:        import com.sun.midp.security.Permissions;
034:        import java.io.DataInputStream;
035:        import java.io.DataOutputStream;
036:        import java.io.InputStream;
037:        import java.io.OutputStream;
038:        import java.util.Vector;
039:        import javax.microedition.io.Connector;
040:        import javax.microedition.io.Connection;
041:        import javax.wireless.messaging.Message;
042:        import javax.wireless.messaging.MessageConnection;
043:
044:        // Exceptions
045:        import java.io.IOException;
046:        import java.io.InterruptedIOException;
047:
048:        /**
049:         * MMS message connection implementation.
050:         *
051:         * <code>Protocol</code> itself is not instantiated. Instead, the application
052:         * calls <code>Connector.open</code> with an MMS URL string and obtains a
053:         * {@link javax.wireless.messaging.MessageConnection MessageConnection}
054:         * object. It is an instance of <code>MessageConnection</code> that is
055:         * instantiated. The Generic Connection Framework mechanism in CLDC will return
056:         * a <code>Protocol</code> object, which is the implementation of
057:         * <code>MessageConnection</code>. The <code>Protocol</code> object represents a
058:         * connection to a low-level transport mechanism.
059:         * <p>
060:         * Optional packages, such as <code>Protocol</code>, cannot reside in small
061:         * devices. The Generic Connection Framework allows an application to reach the
062:         * optional packages and classes indirectly. For example, an application can be
063:         * written with a string that is used to open a connection. Inside the
064:         * implementation of <code>Connector</code>, the string is mapped to a
065:         *  particular implementation: <code>Protocol</code>, in this case. This allows
066:         * the implementation to be optional even though the interface,
067:         * <code>MessageConnection</code>, is required.
068:         * <p>
069:         * Closing the connection frees an instance of <code>MessageConnection</code>.
070:         * <p>
071:         * The <code>Protocol</code> class contains methods to open and close the
072:         * connection to the low-level transport mechanism. The messages passed on the
073:         * transport mechanism are defined by the {@link MessageObject MessageObject}
074:         * class. Connections can be made in either client mode or server mode.
075:         * <ul>
076:         * <li>Client mode connections are for sending messages only. They are created
077:         * by passing a string identifying a destination address to the
078:         * <code>Connector.open()</code> method.</li>
079:         * <li>Server mode connections are for receiving and sending messages. They are
080:         * created by passing a string that identifies a port, or equivalent, on the
081:         * local host to the <code>Connector.open()</code> method.</li>
082:         * </ul>
083:         * The class also contains methods to send, receive, and construct
084:         * <code>Message</code> objects.
085:         * <p>
086:         * <p>
087:         * This class declares that it implements <code>StreamConnection</code> so it
088:         * can intercept calls to <code>Connector.open*Stream()</code> to throw an
089:         * <code>IllegalArgumentException</code>.
090:         * </p>
091:         */
092:        public class Protocol extends ProtocolBase {
093:
094:            /** Creates a message connection protocol handler. */
095:            public Protocol() {
096:                super ();
097:                ADDRESS_PREFIX = "mms://";
098:            }
099:
100:            /**
101:             * Gets the connection parameter in string mode.
102:             * @return string that contains a parameter 
103:             */
104:            protected String getAppID() {
105:                return appID;
106:            }
107:
108:            /**
109:             * Sets the connection parameter in string mode.
110:             * @param newValue new value of connection parameter 
111:             */
112:            protected void setAppID(String newValue) {
113:                appID = newValue;
114:            }
115:
116:            /**
117:             * The internal representation of the MMS message.
118:             */
119:            private class MMSPacket {
120:                /** The sender's address. */
121:                public byte[] fromAddress;
122:                /** The application ID associated with the message. */
123:                public byte[] appID;
124:                /** The application ID to which replies will be sent. */
125:                public byte[] replyToAppID;
126:                /** Entire message contents. */
127:                public byte[] message;
128:            };
129:
130:            /*
131:             * Native function prototypes
132:             */
133:
134:            /**
135:             * Native function to open a MMS connection.
136:             *
137:             * @param host The name of the host for this connection. Can be
138:             *     <code>null</code>.
139:             * @param appID The application ID associated with this connection.
140:             * Can be <code>null</code> for unblock sending and receiving messages.
141:             * @param msid The MIDlet suite ID.
142:             *
143:             * @return  returns handle to the open MMS connection.
144:             */
145:            private native int open0(String host, String appID, int msid)
146:                    throws IOException;
147:
148:            /**
149:             * Unblock the receive thread.
150:             *
151:             * @param msid The MIDlet suite ID.
152:             *
153:             * @return  returns handle to the connection.
154:             */
155:            protected int unblock00(int msid) throws IOException {
156:                return open0(null, null, msid);
157:            }
158:
159:            /**
160:             * Native function to close mms connection
161:             *
162:             * @param appID  The application ID associated with this connection.
163:             * @param handle  The MMS handle created when the connection was opened.
164:             * @param deRegister Deregistration appID when parameter is 1.
165:             *
166:             * @return  <code>0</code> if successful; <code>-1</code> for failure.
167:             */
168:            private native int close0(String appID, int handle, int deRegister);
169:
170:            /**
171:             * Close connection.
172:             *
173:             * @param connHandle handle returned by open0
174:             * @param deRegister Deregistration appID when parameter is 1.
175:             * @return    0 on success, -1 on failure
176:             */
177:            protected int close00(int connHandle, int deRegister) {
178:                return close0(appID, connHandle, deRegister);
179:            }
180:
181:            /**
182:             * Native function to get the device phone number
183:             *
184:             * @return  the phone number of device.
185:             */
186:            private native String getPhoneNumber0();
187:
188:            /**
189:             * Sends an MMS message.
190:             *
191:             * @param handle The handle to the open MMS connection.
192:             * @param toAddress The recipient's MMS address.
193:             * @param fromAddress The sender's MMS address.
194:             * @param appID The application ID to be matched against incoming messages.
195:             * @param replyToAppID The ID of the application that processes replies.
196:             * @param msgHeader The message header context.
197:             * @param msgBody The message body context.
198:             *
199:             * @return the status of <code>0</code>, when bytes were sent;
200:             *	<code>&lt;0</code> when there is an error (This is accompanied by
201:             *	an exception.).
202:             */
203:            private native int send0(int handle, String toAddress,
204:                    String fromAddress, String appID, String replyToAppID,
205:                    byte[] msgHeader, byte[] msgBody) throws IOException;
206:
207:            /**
208:             * Receives a MMS message.
209:             *
210:             * @param handle The handle to the the MMS connection.
211:             * @param appID The application ID to be matched against incoming messages.
212:             * @param msid The MIDlet suite ID.
213:             * @param packet The received message.
214:             *
215:             * @return    The number of bytes received.
216:             *
217:             * @exception IOException  if an I/O error occurs
218:             */
219:            private native int receive0(int handle, String appID, int msid,
220:                    MMSPacket packet) throws IOException;
221:
222:            /**
223:             * Waits until message available
224:             *
225:             * @param appID  The application ID associated with this connection.
226:             * @param handle  The handle to the MMS connection.
227:             *
228:             * @return  <code>0</code> on success, <code>-1</code> on failure
229:             *
230:             * @exception IOException  if an I/O error occurs
231:             */
232:            private native int waitUntilMessageAvailable0(String appID,
233:                    int handle) throws IOException;
234:
235:            /**
236:             * Waits until message available
237:             *
238:             * @param handle handle to connection
239:             * @return 0 on success, -1 on failure
240:             * @exception IOException  if an I/O error occurs
241:             */
242:            protected int waitUntilMessageAvailable00(int handle)
243:                    throws IOException {
244:                return waitUntilMessageAvailable0(appID, handle);
245:            }
246:
247:            /**
248:             * Computes the number of transport-layer segments that would be required to
249:             * send the given message.
250:             *
251:             * @param msgBuffer The message to be sent.
252:             * @param msgLen The length of the message.
253:             * @param msgType The message type: binary or text.
254:             * @param hasPort Indicates if the message includes a source or destination
255:             *     port number.
256:             *
257:             * @return The number of transport-layer segments required to send the
258:             *     message.
259:             */
260:            private native int numberOfSegments0(byte msgBuffer[], int msgLen,
261:                    int msgType, boolean hasPort);
262:
263:            /*
264:             * Helper methods
265:             */
266:
267:            /**
268:             * Checks the internal setting of the receive permission. Called from
269:             * the <code>receive</code> and <code>setMessageListener</code> methods.
270:             *
271:             * @exception InterruptedIOException if permission dialog was pre-empted.
272:             */
273:            protected void checkReceivePermission()
274:                    throws InterruptedIOException {
275:
276:                // Check for permission to receive.
277:                if (readPermission == false) {
278:                    try {
279:                        midletSuite.checkForPermission(Permissions.MMS_RECEIVE,
280:                                "mms:receive");
281:                        readPermission = true;
282:                    } catch (InterruptedException ie) {
283:                        throw new InterruptedIOException(
284:                                "Interrupted while trying "
285:                                        + "to ask the user permission.");
286:                    }
287:                }
288:            }
289:
290:            /*
291:             * MessageConnection Interface
292:             */
293:
294:            /**
295:             * Construct a new message object of a text, binary or multipart message
296:             * type and specify a destination address. When a
297:             * <code>MULTIPART_MESSAGE</code> constant is passed in, the created object
298:             * implements the <code>MultipartMessage</code> interface.
299:             * <p>
300:             * If this method is called in a sending mode, a new <code>Message</code>
301:             * object is requested from the connection. For example:
302:             * <p>
303:             * <code>Message msg = conn.newMessage(MULTIPART_MESSAGE);</code>
304:             * <p>
305:             * The <code>Message</code> does not have the destination address set. It
306:             * must be set by the application before the message is sent.
307:             * <p>
308:             * If this method is called in receiving mode, the <code>Message</code>
309:             * object does have its address set. The application can act on the object
310:             * to extract the address and message data.
311:             * <p>
312:             * <!-- The <code>type</code> parameter indicates the number of bytes that
313:             * should be allocated for the message. No restrictions are placed on the
314:             * application for the value of <code>size</code>. A value of
315:             * <code>null</code> is permitted and creates a <code>Message</code> object
316:             * with a 0-length message. -->
317:             *
318:             * @param type <code>MULTIPART_MESSAGE</code> is the only type permitted.
319:             *
320:             * @return A new MMS <code>Message</code> object.
321:             */
322:            public Message newMessage(String type) {
323:
324:                String address = null;
325:
326:                // Provide the default address from the original open.
327:                if (host != null) {
328:                    address = ADDRESS_PREFIX + host;
329:                    if (appID != null) {
330:                        address = address + ":" + appID;
331:                    }
332:                }
333:
334:                return newMessage(type, address);
335:            }
336:
337:            /**
338:             * Construct a new <code>MULTIPART_MESSAGE</code> message object and specify
339:             * a destination address. The <code>MULTIPART_MESSAGE</code> constant must
340:             * be passed in. The created object implements the
341:             * <code>MultipartMessage</code> interface.
342:             * <p>
343:             * The destination address <code>addr</code> has the following format:
344:             * <p>
345:             * <code>mms://<em>phone_number</em>:<em>application_id</em></code>
346:             *
347:             * @param type <code>MULTIPART_MESSAGE</code> is the only type permitted.
348:             * @param addr  The destination address of the message.
349:             *
350:             * @return A new MMS <code>Message</code> object.
351:             */
352:            public Message newMessage(String type, String addr) {
353:
354:                if (!type.equals(MessageConnection.MULTIPART_MESSAGE)) {
355:                    throw new IllegalArgumentException(
356:                            "Message type not supported.");
357:                }
358:
359:                return new MultipartObject(addr);
360:            }
361:
362:            /**
363:             * Send an MMS message over the connection. The data are extracted from the
364:             * <code>Message</code> object payload for use by the underlying transport
365:             * layer.
366:             *
367:             * @param msg  A <code>Message</code> object.
368:             *
369:             * @exception java.io.IOException if the message could not be sent
370:             *            or because of network failure.
371:             * @exception java.lang.IllegalArgumentException if the message is
372:             *            incomplete or contains invalid information. This exception
373:             *            is also thrown if the payload of the message exceeds
374:             *            the maximum length for the given messaging protocol.
375:             * @exception java.io.InterruptedIOException if a timeout occurs while
376:             *            either trying to send the message or if this
377:             *            <code>Connection</code> object is closed during this
378:             *            <code>send</code> operation.
379:             * @exception java.lang.NullPointerException if the parameter is null.
380:             * @exception java.lang.SecurityException if the application does not
381:             *            have permission to send the message.
382:             */
383:            public void send(Message msg) throws IOException {
384:
385:                if (msg == null) {
386:                    throw new NullPointerException("Null message");
387:                }
388:
389:                // If this isn't a multipart message, bail out.
390:                if (!(msg instanceof  MultipartObject)) {
391:                    throw new IllegalArgumentException(
392:                            "Unsupported message type");
393:                }
394:
395:                // Make sure the connection is still open.
396:                ensureOpen();
397:
398:                // Create the multi-part object that will be used below.
399:                MultipartObject mpo = (MultipartObject) msg;
400:
401:                /*
402:                 * Check for valid MMS URL connection format. Note that the addresses in
403:                 * the lists are not used. This is simply a check to make sure that the
404:                 * addresses can be placed into the multipart object's header when the
405:                 * header and message are bundled within MultipartObject.
406:                 *
407:                 * Process each MMS address in the to:, cc: and bcc: address lists. An
408:                 * MMS address assumes this form: address:appID
409:                 *
410:                 * Each MMS address is parsed to extract the address and application ID
411:                 * data. Those parts are then checked for validity.
412:                 *
413:                 * The loop starts by processing all addresses in the to: field (if
414:                 * any), followed by the addresses in the cc: list, then the bcc: list.
415:                 *
416:                 */
417:                Vector allAddresses = new Vector();
418:                String[] addresses = mpo.getAddresses("to");
419:                int currIndex = 0;
420:                boolean checkedTo = false;
421:                boolean checkedCC = false;
422:
423:                // The application ID extracted from an address in the address list.
424:                String parsedAppID = null;
425:                while (true) {
426:
427:                    /*
428:                     * If no addresses were in the to: field, or if all addresses have
429:                     * been extracted and checked from the current address list
430:                     * (Initially, the to: list), then continue to process the cc: list
431:                     * (if any), next, followed by the bcc: list.
432:                     */
433:                    if (addresses == null || currIndex >= addresses.length) {
434:
435:                        if (!checkedTo) {
436:
437:                            // The to: list has been processed. Process cc: list, next.
438:                            checkedTo = true;
439:                            addresses = mpo.getAddresses("cc");
440:                            currIndex = 0;
441:                            continue;
442:
443:                        } else if (!checkedCC) {
444:
445:                            // The cc: list has been processed. Process bcc: list, next.
446:                            checkedCC = true;
447:                            addresses = mpo.getAddresses("bcc");
448:                            currIndex = 0;
449:                            continue;
450:                        } else {
451:
452:                            /*
453:                             * The to:, cc: and bcc: lists have now been checked, so
454:                             * bail out of the while() loop.
455:                             */
456:                            break;
457:                        }
458:                    }
459:
460:                    /*
461:                     * Pick up the next address and add it to the list. Then, parse it
462:                     * to extract the address and application ID parts.
463:                     */
464:                    String addr = addresses[currIndex++];
465:                    allAddresses.addElement(addr);
466:
467:                    MMSAddress parsedAddress = MMSAddress
468:                            .getParsedMMSAddress(addr);
469:
470:                    if (parsedAddress == null
471:                            || parsedAddress.type == MMSAddress.INVALID_ADDRESS
472:                            || parsedAddress.type == MMSAddress.APP_ID) {
473:                        throw new IllegalArgumentException(
474:                                "Invalid MMS address: " + addr);
475:                    }
476:
477:                    if (parsedAppID == null) {
478:                        parsedAppID = parsedAddress.appId;
479:                    } else if (parsedAddress.appId != null
480:                            && !parsedAppID.equals(parsedAddress.appId)) {
481:                        throw new IllegalArgumentException(
482:                                "Only one Application-ID "
483:                                        + "can be specified per message");
484:                    }
485:
486:                } // while
487:
488:                if (allAddresses.size() == 0) {
489:                    throw new IllegalArgumentException(
490:                            "No to, cc, or bcc addresses.");
491:                }
492:
493:                /*
494:                 * Since JTWI requires the destination phone number (not port)
495:                 * and the number of messages to be displayed in the permission
496:                 * dialog to the user, the permission check must happen after the
497:                 * address check and message disassembly.
498:                 */
499:                try {
500:                    /*
501:                     * IMPL_NOTE: (Original comment for MMS): Add the display of the addresses
502:                     * in a nice way, and the size of all attachments and total size, as
503:                     * per page 66 (Appendix E) of the specification.
504:                     *
505:                     * Nicer display can happen by creating an MMSAddressList class that
506:                     * extends Vector and overrides toString().
507:                     *
508:                     */
509:                    midletSuite.checkForPermission(Permissions.MMS_SEND,
510:                            allAddresses.toString(), Integer
511:                                    .toString(numberOfSegments(msg)));
512:                } catch (InterruptedException ie) {
513:                    throw new InterruptedIOException(
514:                            "Interrupted while trying to ask the user permission");
515:                }
516:
517:                // Construct the target address protocol string.
518:                String messageAppID = mpo.getApplicationID();
519:                String toAddress = "mms://:";
520:                if (messageAppID != null) {
521:                    toAddress = toAddress + messageAppID;
522:                }
523:
524:                /*
525:                 * If no application ID was supplied, use the ID that was used to open
526:                 * the connection as the default ID.
527:                 */
528:                String replyToAppID = null;
529:                if (messageAppID != null && host == null) {
530:                    replyToAppID = appID;
531:                    mpo.setReplyToApplicationID(replyToAppID);
532:                }
533:
534:                // Retain the original "from:" address.
535:                String oldFromAddress = ((MessageObject) mpo).getAddress();
536:
537:                // Create the "reply-to" information.
538:                String phoneNumber = getPhoneNumber0();
539:                String fromAddress = "mms://" + phoneNumber;
540:                if (replyToAppID != null) {
541:                    fromAddress = fromAddress + ":" + replyToAppID;
542:                }
543:                mpo.setFromAddress(fromAddress);
544:
545:                // Send the message and reply information.
546:                byte[] header = mpo.getHeaderAsByteArray();
547:                byte[] body = mpo.getBodyAsByteArray();
548:                try {
549:                    send0(connHandle, toAddress, fromAddress, messageAppID,
550:                            replyToAppID, header, body);
551:                } catch (IOException ex) {
552:                    io2InterruptedIOExc(ex, "sending");
553:                }
554:
555:                // Reset the from: address to its original form.
556:                mpo.setFromAddress(oldFromAddress);
557:            }
558:
559:            /**
560:             * Receives the bytes that have been sent over the connection, constructs a
561:             * <code>MultipartMessage</code> object, and returns the message.
562:             * <p>
563:             * If there are no <code>MultipartMessage</code>s waiting on the connection,
564:             * this method will block until a message is received, or the
565:             * <code>MessageConnection</code> is closed.
566:             *
567:             * @return  A <code>MultipartMessage</code> object.
568:             *
569:             * @exception java.io.IOException  if an error occurs while receiving a
570:             *            message.
571:             * @exception java.io.InterruptedIOException if this
572:             *            <code>MessageConnection</code> object is closed during this
573:             *            receive method call.
574:             * @exception java.lang.SecurityException if the application does not have
575:             *            permission to receive messages using the given application ID.
576:             */
577:            public synchronized Message receive() throws IOException {
578:
579:                if (host != null) {
580:                    throw new IOException(
581:                            "Can not receive from client only connection: "
582:                                    + host);
583:                }
584:
585:                // Check for permission to receive.
586:                checkReceivePermission();
587:
588:                // Make sure the connection is still open.
589:                ensureOpen();
590:
591:                // The connection must be read-only with no host address.
592:                if (((m_mode & Connector.READ) == 0) || (host != null)) {
593:                    throw new IOException("Invalid connection mode.");
594:                }
595:
596:                // No message received yet.
597:                Message msg = null;
598:                int length = 0;
599:
600:                try {
601:
602:                    MMSPacket mmsPacket = new MMSPacket();
603:
604:                    /*
605:                     * Packet has been received and deleted from inbox.
606:                     * Time to wake up receive thread.
607:                     */
608:                    // Pick up the message from the message pool.
609:                    length = receive0(connHandle, appID, midletSuite.getID(),
610:                            mmsPacket);
611:
612:                    if (length == 0) {
613:                        throw new InterruptedIOException("No message received.");
614:                    }
615:
616:                    if (length > 0) {
617:
618:                        /*
619:                         * Convert the message data into a multipart message. The
620:                         * message packet contains the appID that goes with the message
621:                         * as well as the entire message content in a big byte[] lump.
622:                         */
623:                        msg = MultipartObject
624:                                .createFromByteArray(mmsPacket.message);
625:
626:                        // IMPL_NOTE: KEEP ?
627:                        // IMPL_NOTE: msg.setTimeStamp(tm.getTimeStamp());
628:
629:                        String fromAddress = null;
630:                        if (mmsPacket.fromAddress != null) {
631:                            fromAddress = new String(mmsPacket.fromAddress);
632:                        }
633:
634:                        String replyToAppID;
635:                        if (mmsPacket.replyToAppID == null) {
636:                            replyToAppID = null;
637:                        } else {
638:                            replyToAppID = new String(mmsPacket.replyToAppID);
639:                        }
640:
641:                        ((MultipartObject) msg).setFromAddress(fromAddress);
642:                        String phoneNumber = getPhoneNumber0();
643:                        ((MultipartObject) msg).fixupReceivedMessageAddresses(
644:                                fromAddress, phoneNumber);
645:                    }
646:
647:                } catch (InterruptedIOException ex) {
648:                    length = 0; // Avoid the "finally" exception, below.
649:                    throw new InterruptedIOException("MMS connection closed.");
650:                } catch (IOException ex) {
651:                    io2InterruptedIOExc(ex, "receiving");
652:                } finally {
653:                    if (length < 0) {
654:                        throw new InterruptedIOException("Connection closed.");
655:                    }
656:                }
657:
658:                return msg;
659:            }
660:
661:            /**
662:             * Returns the number of segments required to send the given
663:             * <code>Message</code>.
664:             * <p>
665:             * Note: The message is not actually sent. This method will compute the
666:             * number of segments needed when this message is split into the protocol
667:             * segments using the appropriate features of the underlying protocol. This
668:             * method does not take the possible limitations of the implementation into
669:             * account, which may limit the number of segments that can be sent, using
670:             * this feature. These limitations are protocol-specific and are documented
671:             * with the adapter definition for that protocol.
672:             * </p>
673:             * @param msg The <code>MultipartObject</code>message to be used for
674:             *     the computation.
675:             *
676:             * @return  The number of protocol segments needed for sending the message.
677:             *     Returns <code>0</code> if the <code>Message</code> object cannot be
678:             *     sent using the underlying protocol.
679:             */
680:            public int numberOfSegments(Message msg) {
681:
682:                if (!(msg instanceof  MultipartObject)) {
683:                    return 0;
684:                }
685:
686:                /** Number of segments that need to be sent. */
687:                int segments = 0;
688:
689:                byte[] msgBuffer = null;
690:                try {
691:                    msgBuffer = ((MultipartObject) msg).getAsByteArray();
692:                } catch (IOException ioe) {
693:                    // ignore this.
694:                }
695:
696:                // Pick up the message length.
697:                if (msgBuffer != null) {
698:
699:                    // There is always a "port" (Application ID).
700:                    boolean hasPort = true;
701:
702:                    /* Compute the total number of transport-layer segments. */
703:                    segments = numberOfSegments0(msgBuffer, msgBuffer.length,
704:                            0, hasPort);
705:                }
706:
707:                return segments;
708:            }
709:
710:            /**
711:             * Closes the connection. Resets the connection <code>open</code> flag to
712:             * <code>false</code>. Subsequent operations on a closed connection should
713:             * throw an appropriate exception.
714:             *
715:             * @exception IOException  if an I/O error occurs
716:             */
717:            public void close() throws IOException {
718:
719:                /*
720:                 * Set appID to null, in order to quit out of the while loop
721:                 * in the receiver thread.
722:                 */
723:                String save_appID = null;
724:                if (appID != null) {
725:                    save_appID = new String(appID);
726:                }
727:
728:                appID = null;
729:
730:                synchronized (closeLock) {
731:                    if (open) {
732:                        /*
733:                         * Reset open flag early to prevent receive0 executed by 
734:                         * concurrent thread to operate on partially closed 
735:                         * connection 
736:                         */
737:                        open = false; /* Close the connection and unregister the application ID. */
738:                        close0(save_appID, connHandle, 1);
739:
740:                        setMessageListener(null);
741:
742:                        /*
743:                         * Reset handle and other params to default
744:                         * values. Multiple calls to close() are allowed
745:                         * by the spec and the resetting would prevent any
746:                         * strange behaviour.
747:                         */
748:                        connHandle = 0;
749:                        host = null;
750:                        m_mode = 0;
751:                    }
752:                }
753:            }
754:
755:            /*
756:             * ConnectionBaseInterface Interface
757:             */
758:
759:            /**
760:             * Opens a connection. This method is called from the
761:             * <code>Connector.open()</code> method to obtain the destination address
762:             * given in the <code>name</code> parameter.
763:             * <p>
764:             * The format for the <code>name</code> string for this method is:
765:             * <p>
766:             * <code>mms://[<em>phone_number</em>]:[<em>application_id</em>]</code>
767:             * <p>
768:             * where the <em>phone_number</em> is optional. If the <em>phone_number</em>
769:             * parameter is present, the connection is being opened in client mode. This
770:             * means that messages can be sent. If the parameter is absent, the
771:             * connection is being opened in server mode. This means that messages can
772:             * be sent and received.
773:             * <p>
774:             * The connection that is opened is to a low-level transport mechanism which
775:             * can be any of the following:
776:             * <ul>
777:             *   <li>A datagram Short Message Peer-to-Peer (SMPP) to a service center.
778:             *   <li>A <code>comm</code> connection to a phone device with AT-commands.
779:             *   <li>A native MMS stack.
780:             * </ul>
781:             * Currently, the <code>mode</code> and <code>timeouts</code> parameters are
782:             * ignored.
783:             *
784:             * @param name  The target of the connection.
785:             * @param mode  Indicates whether the caller intends to write to the
786:             *              connection. Currently, this parameter is ignored.
787:             * @param timeouts  Indicates whether the caller wants timeout exceptions.
788:             *              Currently, this parameter is ignored.
789:             *
790:             * @return  This connection.
791:             *
792:             * @exception IOException  if the connection is closed or unavailable.
793:             */
794:            public Connection openPrim(String name, int mode, boolean timeouts)
795:                    throws IOException {
796:
797:                return openPrimInternal(name, mode, timeouts);
798:            }
799:
800:            /*
801:             * StreamConnection Interface
802:             */
803:
804:            /**
805:             * Open and return an input stream for a connection. This method always
806:             * throws <code>IllegalArgumentException</code>.
807:             *
808:             * @return                              An input stream.
809:             * @exception IOException               if an I/O error occurs.
810:             * @exception IllegalArgumentException  is thrown for all requests.
811:             */
812:            public InputStream openInputStream() throws IOException {
813:                throw new IllegalArgumentException("Not supported.");
814:            }
815:
816:            /**
817:             * Open and return a data input stream for a connection. This method always
818:             * throws <code>IllegalArgumentException</code>.
819:             *
820:             * @return                              An input stream.
821:             * @exception IOException               if an I/O error occurs.
822:             * @exception IllegalArgumentException  is thrown for all requests.
823:             */
824:            public DataInputStream openDataInputStream() throws IOException {
825:                throw new IllegalArgumentException("Not supported.");
826:            }
827:
828:            /**
829:             * Open and return an output stream for a connection. This method always
830:             * throws <code>IllegalArgumentException</code>.
831:             *
832:             * @return                              An output stream.
833:             * @exception IOException               if an I/O error occurs.
834:             * @exception IllegalArgumentException  is thrown for all requests.
835:             */
836:            public OutputStream openOutputStream() throws IOException {
837:                throw new IllegalArgumentException("Not supported.");
838:            }
839:
840:            /**
841:             * Open and return a data output stream for a connection. This method always
842:             * throws <code>IllegalArgumentException</code>.
843:             *
844:             * @return                              An output stream.
845:             * @exception IOException               if an I/O error occurs.
846:             * @exception IllegalArgumentException  is thrown for all requests.
847:             */
848:            public DataOutputStream openDataOutputStream() throws IOException {
849:                throw new IllegalArgumentException("Not supported.");
850:            }
851:
852:            /*
853:             * Protocol members
854:             */
855:
856:            /**
857:             * Opens a connection. This method is called from the
858:             * <code>Connector.open()</code> method to obtain the destination address
859:             * given in the <code>name</code> parameter.
860:             * <p>
861:             * The format for the <code>name</code> string for this method is:
862:             * <p>
863:             * <code>mms://[<em>phone_number</em>]:[<em>application_id</em>]</code>
864:             * <p>
865:             * where the <em>phone_number</em> is optional. If the <em>phone_number</em>
866:             * parameter is present, the connection is being opened in client mode. This
867:             * means that messages can be sent. If the parameter is absent, the
868:             * connection is being opened in server mode. This means that messages can
869:             * be sent and received.
870:             * <p>
871:             * The connection that is opened is to a low-level transport mechanism which
872:             * can be any of the following:
873:             * <ul>
874:             *   <li>A datagram Short Message Peer-to-Peer (SMPP) to a service center.
875:             *   <li>A <code>comm</code> connection to a phone device with AT-commands.
876:             *   <li>A native MMS stack.
877:             * </ul>
878:             * Currently, the <code>mode</code> and <code>timeouts</code> parameters are
879:             * ignored.
880:             *
881:             * @param name  The target of the connection.
882:             * @param mode  Indicates whether the caller intends to write to the
883:             *              connection. Currently, this parameter is ignored.
884:             * @param timeouts  Indicates whether the caller wants timeout exceptions.
885:             *              Currently, this parameter is ignored.
886:             *
887:             * @return  This connection.
888:             *
889:             * @exception IOException  if the connection is closed or unavailable.
890:             * @exception IllegalArgumentException  if the parameters are invalid
891:             */
892:            public synchronized Connection openPrimInternal(String name,
893:                    int mode, boolean timeouts) throws IOException {
894:
895:                /*
896:                 * The general form of a MMS address is <code>mms://host:port</code>.
897:                 * The form at this point should now be <code>//host:port</code>
898:                 */
899:                if ((name == null) || (name.length() <= 2)
900:                        || (name.charAt(0) != '/') || (name.charAt(1) != '/')) {
901:
902:                    throw new IllegalArgumentException(
903:                            "Missing protocol separator.");
904:                }
905:
906:                String fullAddress = "mms:" + name;
907:
908:                MMSAddress parsedAddress = MMSAddress
909:                        .getParsedMMSAddress(fullAddress);
910:                if (parsedAddress == null) {
911:                    throw new IllegalArgumentException(
912:                            "Invalid MMS connection URL");
913:                }
914:
915:                host = null;
916:                if (parsedAddress.address != null) {
917:                    host = new String(parsedAddress.address);
918:                }
919:
920:                appID = null;
921:                if (parsedAddress.appId != null) {
922:                    appID = new String(parsedAddress.appId);
923:                }
924:
925:                // Make sure the I/O constraint is READ, WRITE or READ_WRITE, only.
926:                if ((mode != Connector.READ) && (mode != Connector.WRITE)
927:                        && (mode != Connector.READ_WRITE)) {
928:                    throw new IllegalArgumentException("Invalid mode");
929:                }
930:
931:                /*
932:                 * If <code>host == null</code>, then this is a server endpoint at
933:                 * the supplied <code>appId</code>.
934:                 *
935:                 * If <code>host != null</code>, then this is a client endpoint at an
936:                 * application-id decided by the system, and the default address for
937:                 * MMS messages to be sent is <code>mms://host:appId</code>.
938:                 */
939:                if (mode == Connector.READ && host != null && host.length() > 0) {
940:                    throw new IllegalArgumentException("Cannot read on "
941:                            + "a client connection.");
942:                }
943:
944:                /*
945:                 * Perform a one-time check to see if the application has the permission
946:                 * to use this connection type.
947:                 */
948:                if (openPermission == false) {
949:                    try {
950:                        midletSuite.checkForPermission(Permissions.MMS_SERVER,
951:                                "mms:open");
952:                        openPermission = true;
953:                    } catch (InterruptedException ie) {
954:                        throw new InterruptedIOException(
955:                                "Interrupted while trying "
956:                                        + "to ask the user permission");
957:                    }
958:                }
959:
960:                try {
961:                    connHandle = open0(host, appID, midletSuite.getID());
962:                } catch (IOException ioe) {
963:                    m_mode = 0;
964:                    throw new IOException("Unable to open MMS connection: "
965:                            + ioe.getMessage());
966:                } catch (OutOfMemoryError oome) {
967:                    m_mode = 0;
968:                    throw new IOException("Unable to open MMS connection: "
969:                            + oome.getMessage());
970:                }
971:                open = true;
972:
973:                m_mode = mode;
974:
975:                // Return this connection.
976:                return this;
977:            }
978:
979:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.