|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 package com.nokia.mj.impl.sms; |
|
19 |
|
20 import java.io.IOException; |
|
21 import java.io.InterruptedIOException; |
|
22 |
|
23 import javax.wireless.messaging.Message; |
|
24 import javax.wireless.messaging.TextMessage; |
|
25 import javax.wireless.messaging.BinaryMessage; |
|
26 import javax.wireless.messaging.MessageListener; |
|
27 import javax.wireless.messaging.MessageConnection; |
|
28 |
|
29 import com.nokia.mj.impl.utils.Logger; |
|
30 import com.nokia.mj.impl.smscbs.utils.WmaUrl; |
|
31 import com.nokia.mj.impl.rt.support.ShutdownListener; |
|
32 import com.nokia.mj.impl.rt.support.ApplicationUtils; |
|
33 /** |
|
34 * The SMSConnectionImpl used for sending and receiving Binary/Text Messages. It |
|
35 * offers methods for creating Binary/Text Messages and for sending them. It |
|
36 * implements the receiving functionality. |
|
37 */ |
|
38 public class SMSConnectionImpl implements MessageConnection |
|
39 { |
|
40 private static final String SERVER_MSG = |
|
41 "Message Connection must be a Server connection"; |
|
42 |
|
43 private static final int INITIAL = 0; |
|
44 |
|
45 private static final int OPEN = 1; |
|
46 |
|
47 private static final int CLOSED = 2; |
|
48 |
|
49 private static final int ERROR = 3; |
|
50 |
|
51 private static final int MAXIMUM_MESAGE_SEGMENTS_SUPPORTED = 10; |
|
52 |
|
53 //current Connection state |
|
54 private int iState; |
|
55 |
|
56 // any error while receiving message |
|
57 private int iRecvError; |
|
58 |
|
59 //status of send |
|
60 private int iSendResult; |
|
61 |
|
62 // waiting for message |
|
63 private int iMessageWaiting; |
|
64 |
|
65 // number of received messages |
|
66 private int iMessagesOnQueue; |
|
67 |
|
68 // number of notifications to be done |
|
69 private int iMessageNotificationsToMake; |
|
70 |
|
71 // handle to the native side |
|
72 private int iNativeHandle; |
|
73 |
|
74 // any message notification missed |
|
75 private boolean iMissedMessage; |
|
76 |
|
77 // Is Server Connection |
|
78 private boolean iServerConnection; |
|
79 |
|
80 // synchronization for reading message |
|
81 private final Object iReadLock; |
|
82 |
|
83 // synchronization for sending message |
|
84 private final Object iWriteLock; |
|
85 |
|
86 // synchronization for closing |
|
87 private final Object iCloseLock; |
|
88 |
|
89 // synchronization for receiving |
|
90 private final Object iMessageLock; |
|
91 |
|
92 // synchronization for sending |
|
93 private final Object iSendLock; |
|
94 |
|
95 // the listener used for messages receiving notifications |
|
96 private MessageListener iMessageListener; |
|
97 |
|
98 private WmaUrl iUri; |
|
99 |
|
100 public SMSConnectionImpl(WmaUrl aMsgUri, boolean aServerMode) |
|
101 throws IOException |
|
102 { |
|
103 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
104 "+ SMSConnectionImpl::SMSConnectionImpl"); |
|
105 iUri = aMsgUri; |
|
106 iState = INITIAL; |
|
107 iServerConnection = aServerMode; |
|
108 //create the native side peer |
|
109 iNativeHandle = _createConnection(iUri.getAbsoluteUri(), |
|
110 iServerConnection); |
|
111 iReadLock = new Object(); |
|
112 iWriteLock = new Object(); |
|
113 iCloseLock = new Object(); |
|
114 iMessageLock = new Object(); |
|
115 iSendLock = new Object(); |
|
116 //register for shutdown listening |
|
117 setShutdownListener(); |
|
118 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
119 "- SMSConnectionImpl::SMSConnectionImpl"); |
|
120 } |
|
121 |
|
122 /* |
|
123 * This function registers this object for shutDown. |
|
124 */ |
|
125 private void setShutdownListener() |
|
126 { |
|
127 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
128 "+ SMSConnectionImpl::setShutdownListener"); |
|
129 // Get the insatnce of ApplicationUtils. |
|
130 ApplicationUtils appUtils = ApplicationUtils.getInstance(); |
|
131 |
|
132 // Get the name of the application. |
|
133 appUtils.addShutdownListener(new ShutdownListener() |
|
134 { |
|
135 //The method that gets called when Application is shutting down |
|
136 public void shuttingDown() |
|
137 { |
|
138 try |
|
139 { |
|
140 close(); |
|
141 } |
|
142 catch (IOException ex) |
|
143 { |
|
144 //Nothing to do, just ignore |
|
145 Logger.ELOG(Logger.EWMA, ex.toString(), ex); |
|
146 } |
|
147 } |
|
148 }); |
|
149 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
150 "- SMSConnectionImpl::setShutdownListener"); |
|
151 } |
|
152 |
|
153 /** |
|
154 * open() is only called when a MIDlet calls Connector.open() a MIDlet will |
|
155 * not be able to access the Connection until open() has completed and a |
|
156 * reference has been returned. It should then only be called once, by only |
|
157 * one thread. particularly, a Connection cannot be closed by a MIDlet until |
|
158 * it has been fully opened. |
|
159 * @exceptions Throws IOException if any error while Opening |
|
160 */ |
|
161 public void open() throws IOException |
|
162 { |
|
163 Logger.LOG(Logger.EWMA, Logger.EInfo,"+ SMSConnectionImpl::open"); |
|
164 if (iState == INITIAL) |
|
165 { |
|
166 iState = OPEN; |
|
167 //in case of server connection a notifier thread is created which |
|
168 //waits in the native side and informs the application when there |
|
169 //is an incoming message. |
|
170 if (iServerConnection) |
|
171 { |
|
172 synchronized (iCloseLock) |
|
173 { |
|
174 new Thread(new Runnable() |
|
175 { |
|
176 public void run() |
|
177 { |
|
178 _openConnection(iNativeHandle); |
|
179 } |
|
180 }).start(); |
|
181 } |
|
182 } |
|
183 } |
|
184 Logger.LOG(Logger.EWMA, Logger.EInfo,"- SMSConnectionImpl::open"); |
|
185 } |
|
186 |
|
187 /** |
|
188 * close() is only called when a MIDlet calls close() on a connection that |
|
189 * is opened by calling Connector.open() A MIDlet will not be able to access |
|
190 * the Connection after calling close() on that connection. |
|
191 * @exceptions Throws IOException if any error while closing. |
|
192 */ |
|
193 public void close() throws IOException |
|
194 { |
|
195 Logger.LOG(Logger.EWMA, Logger.EInfo,"+ SMSConnectionImpl::close"); |
|
196 synchronized (iCloseLock) |
|
197 { |
|
198 if (iState != CLOSED) |
|
199 { |
|
200 iState = CLOSED; |
|
201 _closeConnection(iNativeHandle); |
|
202 |
|
203 //notify the notifier thread if it is waiting for a receive() or |
|
204 //setMessageListener() to be called |
|
205 synchronized (iMessageLock) |
|
206 { |
|
207 iMessageLock.notify(); |
|
208 } |
|
209 //notify the receive operation about connection closed |
|
210 synchronized (iReadLock) |
|
211 { |
|
212 iReadLock.notify(); |
|
213 } |
|
214 _dispose(iNativeHandle); |
|
215 } |
|
216 } |
|
217 Logger.LOG(Logger.EWMA, Logger.EInfo,"- SMSConnectionImpl::close"); |
|
218 } |
|
219 |
|
220 /** |
|
221 * Sets the message listener for this connection |
|
222 * |
|
223 * @param aListener |
|
224 * listener interested for incoming message. |
|
225 * @exceptions throws IOException if the connection is already closed |
|
226 * or this method is called on a client connection. |
|
227 */ |
|
228 public void setMessageListener(MessageListener aListener) |
|
229 throws IOException |
|
230 { |
|
231 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
232 "+ SMSConnectionImpl::setMessageListener"); |
|
233 if (!iServerConnection) |
|
234 { |
|
235 throw new IOException(SERVER_MSG); |
|
236 } |
|
237 |
|
238 if (iState == CLOSED) |
|
239 { |
|
240 throw new IOException( |
|
241 "Setting message listener failed: connection is already closed"); |
|
242 } |
|
243 checkReceivePermission(); |
|
244 synchronized (iReadLock) |
|
245 { |
|
246 iMessageListener = aListener; |
|
247 if (aListener != null) |
|
248 { |
|
249 synchronized (iMessageLock) |
|
250 { |
|
251 iMessageLock.notify(); |
|
252 } |
|
253 } |
|
254 } |
|
255 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
256 "+ SMSConnectionImpl::setMessageListener"); |
|
257 } |
|
258 |
|
259 /** |
|
260 * checks for any error while receiving a message |
|
261 * @exception throws IOException in case of any error |
|
262 */ |
|
263 private final void checkForReceiveError() throws IOException |
|
264 { |
|
265 if (iRecvError !=0) |
|
266 { |
|
267 int err = iRecvError; |
|
268 iRecvError = 0; |
|
269 if (err < 0) |
|
270 { |
|
271 _checkError(err, false); |
|
272 } |
|
273 } |
|
274 } |
|
275 |
|
276 /** |
|
277 * Checks for security permission for receive operation. |
|
278 * @exception throws SecurityException if no valid permission exists. |
|
279 */ |
|
280 protected void checkReceivePermission() |
|
281 { |
|
282 ApplicationUtils appUtils = ApplicationUtils.getInstance(); |
|
283 SMSPermissionImpl permission = new SMSPermissionImpl("sms://*", |
|
284 "receive"); |
|
285 appUtils.checkPermission(permission); |
|
286 } |
|
287 /** |
|
288 * Receive is a 3 step process: 1) Wait for some incoming message 2) |
|
289 * Retrieve the the message 3) Construct a Binary/Text Message |
|
290 * |
|
291 * @exceptions throws IOException if the connection is already closed. |
|
292 * @exceptions throws InterruptedIOException if the connection is closed |
|
293 * while receiving |
|
294 * @returns the constructed message |
|
295 */ |
|
296 public Message receive() throws IOException, InterruptedIOException |
|
297 { |
|
298 Logger.LOG(Logger.EWMA, Logger.EInfo,"+ SMSConnectionImpl::receive"); |
|
299 if (!iServerConnection) |
|
300 { |
|
301 //throw IOException if receive is called on client connection |
|
302 throw new IOException(SERVER_MSG); |
|
303 } |
|
304 Message message = null; |
|
305 synchronized (iReadLock) |
|
306 { |
|
307 //check for connection |
|
308 if (iState == CLOSED) |
|
309 { |
|
310 throw new IOException( |
|
311 "Receiving message failed: connection is already closed"); |
|
312 } |
|
313 if (iUri.isRestrictedPort() == true) |
|
314 { |
|
315 throw new SecurityException( |
|
316 "No permission to receive on port: " + iUri.getPort()); |
|
317 } |
|
318 checkReceivePermission(); |
|
319 //if no messages were there to receive wait till some message |
|
320 //arrives |
|
321 if (iMessagesOnQueue == 0) |
|
322 { |
|
323 iMessageWaiting++; |
|
324 //notify the notifier thread |
|
325 synchronized (iMessageLock) |
|
326 { |
|
327 iMessageLock.notify(); |
|
328 } |
|
329 //wait for incoming message notification |
|
330 try |
|
331 { |
|
332 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
333 "WMA : Waiting for message"); |
|
334 iReadLock.wait(); |
|
335 } |
|
336 catch (InterruptedException ex) |
|
337 { |
|
338 Logger.ELOG(Logger.EWMA, ex.toString(), ex); |
|
339 } |
|
340 } |
|
341 //check for any error while receiving |
|
342 checkForReceiveError(); |
|
343 synchronized (iCloseLock) |
|
344 { |
|
345 String remoteAddress; |
|
346 //if the connection was closed throw InterruptedIOException |
|
347 if (iState == CLOSED) |
|
348 { |
|
349 throw new InterruptedIOException( |
|
350 "Connection closed while receiving message"); |
|
351 } |
|
352 //get the message type ( Text/Binary) |
|
353 final int messageType = _getMessageType(iNativeHandle); |
|
354 if (messageType != SMSMessageImpl.MESSAGE_TEXT && |
|
355 messageType != SMSMessageImpl.MESSAGE_BINARY) |
|
356 { |
|
357 if (messageType < 0) |
|
358 { |
|
359 _checkError(messageType, false); |
|
360 } |
|
361 } |
|
362 //get the remote host address |
|
363 remoteAddress = _getHostAddress(iNativeHandle); |
|
364 //get the time stamp of the message |
|
365 final long timestamp = _getTimestamp(iNativeHandle); |
|
366 //construct the message object based on the message type |
|
367 if (messageType == SMSMessageImpl.MESSAGE_TEXT) |
|
368 { |
|
369 //get the text message data. |
|
370 final String textData = (String)_getReceivedMessageData( |
|
371 iNativeHandle, messageType); |
|
372 //construct the text message object |
|
373 TextMessage textMessage = new SMSTextMessageImpl( |
|
374 remoteAddress, timestamp); |
|
375 textMessage.setPayloadText(textData); |
|
376 message = textMessage; |
|
377 } |
|
378 else |
|
379 { |
|
380 //get the Binary message data |
|
381 final byte[] binaryData = (byte[]) _getReceivedMessageData( |
|
382 iNativeHandle, messageType); |
|
383 //construct the binary message object |
|
384 BinaryMessage binaryMessage = new SMSBinaryMessageImpl( |
|
385 remoteAddress, timestamp); |
|
386 binaryMessage.setPayloadData(binaryData); |
|
387 message = binaryMessage; |
|
388 } |
|
389 } |
|
390 iMessagesOnQueue--; |
|
391 } |
|
392 Logger.LOG(Logger.EWMA, Logger.EInfo,"- SMSConnectionImpl::receive"); |
|
393 return message; |
|
394 } |
|
395 |
|
396 /** |
|
397 * Method for creating a Binary/Text Message object. If it is a client |
|
398 * connection The destination address of the newly created messages will be |
|
399 * set to the destination part of the URI provided when this connection was |
|
400 * created. |
|
401 * |
|
402 * @param aType |
|
403 * The type of the message to be created. It can only be |
|
404 * "Binary/Text" |
|
405 */ |
|
406 public Message newMessage(String aType) |
|
407 { |
|
408 String address = null; |
|
409 if (!iServerConnection) |
|
410 { |
|
411 address = iUri.getAbsoluteUri(); |
|
412 } |
|
413 |
|
414 return newMessage(aType, address); |
|
415 } |
|
416 |
|
417 /** |
|
418 * Method for creating a Binary/Text Message object |
|
419 * |
|
420 * @param aType |
|
421 * The type of the message to be created. It can only be |
|
422 * "Binary/Text" |
|
423 * @param aAddress |
|
424 * the destination address of the Message |
|
425 */ |
|
426 public Message newMessage(String aType, String aAddress) |
|
427 { |
|
428 Message msg; |
|
429 if (aType.equals(TEXT_MESSAGE)) |
|
430 { |
|
431 msg = new SMSTextMessageImpl(aAddress, 0); |
|
432 } |
|
433 else if (aType.equals(BINARY_MESSAGE)) |
|
434 { |
|
435 msg = new SMSBinaryMessageImpl(aAddress, 0); |
|
436 } |
|
437 else |
|
438 { |
|
439 throw new IllegalArgumentException( |
|
440 "Message type is invalid: " + aType); |
|
441 } |
|
442 |
|
443 return msg; |
|
444 } |
|
445 |
|
446 /** |
|
447 * Returns the number of segments required for sending a |
|
448 * Binary/Text Message. |
|
449 * @param aMsg The Message for which the segments to be found. |
|
450 * @exceptions throws IllegalArguementException if no address is specified |
|
451 * or if the message is not a valid message |
|
452 */ |
|
453 public int numberOfSegments(Message aMsg) |
|
454 { |
|
455 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
456 "+ SMSConnectionImpl::numberOfSegments"); |
|
457 int messageSegments = 0; |
|
458 if (aMsg == null) |
|
459 { |
|
460 throw new NullPointerException("Message parameter is null"); |
|
461 } |
|
462 String address = aMsg.getAddress(); |
|
463 // if it is a serverConnection and address field of the message is null |
|
464 // then it calculates numberOfSegments assuming Port number present. |
|
465 // Because that will be the maximum numberOfSegments required to send |
|
466 // the message. |
|
467 final WmaUrl uri; |
|
468 if (iServerConnection && address != null) |
|
469 { |
|
470 uri = new WmaUrl(address); |
|
471 uri.validateUri(); |
|
472 } |
|
473 else |
|
474 { |
|
475 uri = iUri; |
|
476 } |
|
477 |
|
478 final SMSMessageImpl messageImpl; |
|
479 try |
|
480 { |
|
481 messageImpl = (SMSMessageImpl) aMsg; |
|
482 } |
|
483 catch (ClassCastException ex) |
|
484 { |
|
485 throw new IllegalArgumentException("NumberOfSegments can only" |
|
486 + "be calculated for Text/Binary Message"); |
|
487 } |
|
488 synchronized (iCloseLock) |
|
489 { |
|
490 if (iState != CLOSED) |
|
491 { |
|
492 if (messageImpl.getType() == messageImpl.MESSAGE_TEXT) |
|
493 { |
|
494 |
|
495 messageSegments = _smsTextDataSegments(iNativeHandle, |
|
496 messageImpl.getType(), uri.getHost(), uri.getPort(), |
|
497 messageImpl.getPayloadTextData()); |
|
498 } |
|
499 else |
|
500 { |
|
501 |
|
502 messageSegments = _smsBinaryDataSegments(iNativeHandle, |
|
503 messageImpl.getType(), uri.getHost(), uri.getPort(), |
|
504 messageImpl.getPayloadBinaryData()); |
|
505 } |
|
506 } |
|
507 } |
|
508 if (messageSegments > MAXIMUM_MESAGE_SEGMENTS_SUPPORTED) |
|
509 { |
|
510 messageSegments = 0; |
|
511 } |
|
512 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
513 "+ SMSConnectionImpl::numberOfSegments"); |
|
514 return messageSegments; |
|
515 } |
|
516 |
|
517 /** |
|
518 * Method for sending a certain message. Only Binary/Text Messages can be |
|
519 * sent through this connection. The destination addresses of the Message to |
|
520 * be sent have to contain the destination address . |
|
521 * |
|
522 * @param aMsg |
|
523 * The message to be sent |
|
524 * @exceptions throws IOException if there is any n/w problem or if |
|
525 * connection is already closed |
|
526 * @exceptions throws InterruptedIOException if a timeout occurs or if |
|
527 * the connection is closed while sending. |
|
528 * @exceptions throws IllegalArguementException if No address or host is |
|
529 * specified |
|
530 */ |
|
531 public void send(Message aMsg) throws IOException, InterruptedIOException |
|
532 { |
|
533 Logger.LOG(Logger.EWMA, Logger.EInfo, "+ SMSConnectionImpl::send"); |
|
534 int messageSegments = 0; |
|
535 if (aMsg == null) |
|
536 { |
|
537 throw new NullPointerException("Message parameter is null"); |
|
538 } |
|
539 String sendAddress = aMsg.getAddress(); |
|
540 //check whether destination address is specified in the message |
|
541 if (sendAddress == null) |
|
542 { |
|
543 throw new IllegalArgumentException( |
|
544 "Message destination address not specified"); |
|
545 } |
|
546 final WmaUrl uri = new WmaUrl(sendAddress); |
|
547 // validate the address |
|
548 uri.validateUri(); |
|
549 // check whether destination host address is specified in the message |
|
550 if ("".equals(uri.getHost())) |
|
551 { |
|
552 throw new IllegalArgumentException( |
|
553 "Message destination address not specified"); |
|
554 } |
|
555 final SMSMessageImpl messageImpl; |
|
556 try |
|
557 { |
|
558 messageImpl = (SMSMessageImpl) aMsg; |
|
559 } |
|
560 catch (ClassCastException ex) |
|
561 { |
|
562 throw new IllegalArgumentException("The message to be sent with" |
|
563 + "this connection can only be Text/Binary Message"); |
|
564 } |
|
565 // validates the port |
|
566 if (uri.isRestrictedPort() == true) |
|
567 { |
|
568 throw new SecurityException( |
|
569 "No permission to send on port: " + uri.getPort()); |
|
570 } |
|
571 //to synchronize send functionality |
|
572 synchronized (iWriteLock) |
|
573 { |
|
574 synchronized (iSendLock) |
|
575 { |
|
576 // send operation should not be carried out while close |
|
577 // is in progress |
|
578 synchronized (iCloseLock) |
|
579 { |
|
580 //verify whether connection is closed. |
|
581 if (iState == CLOSED) |
|
582 { |
|
583 throw new IOException( |
|
584 "Sending message failed: connection is already closed"); |
|
585 } |
|
586 //calculate the number of message segments required to send this |
|
587 //message |
|
588 if (messageImpl.getType() == messageImpl.MESSAGE_TEXT) |
|
589 { |
|
590 |
|
591 messageSegments = _smsTextDataSegments(iNativeHandle, |
|
592 messageImpl.getType(), uri.getHost(), uri.getPort(), |
|
593 messageImpl.getPayloadTextData()); |
|
594 } |
|
595 else |
|
596 { |
|
597 |
|
598 messageSegments = _smsBinaryDataSegments(iNativeHandle, |
|
599 messageImpl.getType(), uri.getHost(), uri.getPort(), |
|
600 messageImpl.getPayloadBinaryData()); |
|
601 } |
|
602 //check whether message is too big for sending |
|
603 if (messageSegments > MAXIMUM_MESAGE_SEGMENTS_SUPPORTED) |
|
604 { |
|
605 throw new IllegalArgumentException( |
|
606 "Message exceeds the maximum supported segments: " + |
|
607 MAXIMUM_MESAGE_SEGMENTS_SUPPORTED); |
|
608 } |
|
609 ApplicationUtils appUtils = ApplicationUtils.getInstance(); |
|
610 // remove the protocol |
|
611 SMSPermissionImpl permission = new SMSPermissionImpl("sms://*", |
|
612 "send",messageSegments,uri.getHost() |
|
613 + ((uri.getPort() != null |
|
614 && uri.getPort().length() > 0) |
|
615 ? (":" + uri.getPort()) : "")); |
|
616 |
|
617 appUtils.checkPermission(permission); |
|
618 //to allow close operation to succeed while sending, send |
|
619 //operation is carried out in a new thread |
|
620 new Thread(new Runnable() |
|
621 { |
|
622 public void run() |
|
623 { |
|
624 doSend(); |
|
625 } |
|
626 }).start(); |
|
627 //wait till the message was sent successfully |
|
628 try |
|
629 { |
|
630 iSendLock.wait(); |
|
631 } |
|
632 catch (InterruptedException ex) |
|
633 { |
|
634 Logger.ELOG(Logger.EWMA, "Sending a message failed", ex); |
|
635 } |
|
636 if (iSendResult < 0) |
|
637 { |
|
638 _checkError(iSendResult, true); |
|
639 } |
|
640 } |
|
641 } |
|
642 } |
|
643 Logger.LOG(Logger.EWMA, Logger.EInfo, "- SMSConnectionImpl::send"); |
|
644 } |
|
645 |
|
646 |
|
647 /** |
|
648 * This method runs in seperate thread and unblocks the send with the |
|
649 * send status |
|
650 */ |
|
651 private void doSend() |
|
652 { |
|
653 iSendResult = _sendMessage(iNativeHandle); |
|
654 synchronized (iSendLock) |
|
655 { |
|
656 iSendLock.notify(); |
|
657 } |
|
658 } |
|
659 |
|
660 /** |
|
661 * Callback through which the Native notifies about the receiving of a |
|
662 * Message or any error while receiving a message. |
|
663 * @param1 aReceivedMesgs - number of messages to be received |
|
664 * @param2 aError - any error while receiving a message |
|
665 * |
|
666 */ |
|
667 protected int messageReceiveCallback(int aReceivedMsgs, int aError) |
|
668 { |
|
669 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
670 "+ SMSConnectionImpl::messageReceiveCallback"); |
|
671 synchronized (iMessageLock) |
|
672 { |
|
673 //check either receive was called or a listener was set on this |
|
674 //connection |
|
675 if (0 == iMessageWaiting && (null == iMessageListener)) |
|
676 { |
|
677 //if neither receive nor setMessageListener was called on this |
|
678 //wait for either of them to be called |
|
679 try |
|
680 { |
|
681 iMessageLock.wait(); |
|
682 } |
|
683 catch (InterruptedException ex) |
|
684 { |
|
685 Logger.ELOG(Logger.EWMA, ex.toString(), ex); |
|
686 } |
|
687 } |
|
688 } |
|
689 synchronized (iReadLock) |
|
690 { |
|
691 //calculate number of new messages arrived and to be notified |
|
692 if (aReceivedMsgs > 0) |
|
693 { |
|
694 iMessagesOnQueue += aReceivedMsgs; |
|
695 iMessageNotificationsToMake += aReceivedMsgs; |
|
696 } |
|
697 //incase of any error store that error |
|
698 else |
|
699 { |
|
700 iRecvError = aError; |
|
701 } |
|
702 if (0 != iMessageWaiting) |
|
703 { |
|
704 iMessageWaiting--; |
|
705 //if a receive operation was called notify the receive about |
|
706 //the incoming message |
|
707 iReadLock.notify(); |
|
708 } |
|
709 else if (null != iMessageListener) |
|
710 { |
|
711 //if a listener was set notify the listener about the incoming |
|
712 //messages |
|
713 while (iMessageNotificationsToMake > 0) |
|
714 { |
|
715 iMessageListener.notifyIncomingMessage(this); |
|
716 iMessageNotificationsToMake--; |
|
717 } |
|
718 //incase of an error notify |
|
719 if (iRecvError != 0) |
|
720 { |
|
721 iMessageListener.notifyIncomingMessage(this); |
|
722 } |
|
723 } |
|
724 } |
|
725 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
726 "+ SMSConnectionImpl::messageReceiveCallback"); |
|
727 return ((iState == CLOSED)? -1 : 0); |
|
728 } |
|
729 |
|
730 private native int _createConnection(String aUri, |
|
731 boolean aServerConnection); |
|
732 |
|
733 private native void _openConnection(int aNativeHandle); |
|
734 |
|
735 private native void _closeConnection(int aNativeHandle); |
|
736 |
|
737 private native int _smsTextDataSegments(int aNativePeerHandle, |
|
738 int aMsgType, String aHostAddress, String aHostPort, String aData); |
|
739 |
|
740 private native int _smsBinaryDataSegments(int aNativePeerHandle, |
|
741 int aMsgType, String aHostAddress, String aHostPort, byte[] aData); |
|
742 |
|
743 private native int _sendMessage(int aNativePeerHandle); |
|
744 |
|
745 private native int _getMessageType(int aNativePeerHandle); |
|
746 |
|
747 private native String _getHostAddress(int aNativePeerHandle); |
|
748 |
|
749 private native long _getTimestamp(int aNativePeerHandle); |
|
750 |
|
751 private native Object _getReceivedMessageData(int aNativePeerHandle, |
|
752 int aMsgType); |
|
753 private native void _dispose(int aNativeHandle); |
|
754 |
|
755 private native void _checkError(int aError,boolean aIsSendOperation); |
|
756 } |
|
757 |