|
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 |
|
19 package com.nokia.mj.impl.mms; |
|
20 |
|
21 import java.io.IOException; |
|
22 import java.io.InterruptedIOException; |
|
23 import javax.wireless.messaging.*; |
|
24 |
|
25 import com.nokia.mj.impl.utils.Logger; |
|
26 import com.nokia.mj.impl.mms.MmsPropertyRetriever; |
|
27 import com.nokia.mj.impl.rt.support.ShutdownListener; |
|
28 import com.nokia.mj.impl.rt.support.ApplicationUtils; |
|
29 |
|
30 public final class MMSConnectionImpl implements MessageConnection |
|
31 { |
|
32 private static final int INITIAL = 0; |
|
33 |
|
34 private static final int OPEN = 1; |
|
35 |
|
36 private static final int CLOSED = 2; |
|
37 |
|
38 // current state of execution |
|
39 private int iState; |
|
40 |
|
41 // status of send |
|
42 private int iSendError = 0; |
|
43 |
|
44 // number of received messages |
|
45 private int iMessagesOnQueue; |
|
46 |
|
47 // number of notifications to be done |
|
48 private int iNotificationsToMake; |
|
49 |
|
50 // handle to the native side |
|
51 private int iNativeHandle; |
|
52 |
|
53 // waiting for message |
|
54 private boolean iMessageWaiting; |
|
55 |
|
56 // any message notification missed |
|
57 private boolean iMissedMessage; |
|
58 |
|
59 // Is Server Connection |
|
60 private boolean iServerConnection; |
|
61 |
|
62 // synchronization for reading message |
|
63 private final Object iReadLock; |
|
64 |
|
65 // synchronization for sending |
|
66 private final Object iSendLock; |
|
67 |
|
68 // synchronization for sending message |
|
69 private final Object iWriteLock; |
|
70 |
|
71 // synchronization for closing |
|
72 private final Object iCloseLock; |
|
73 |
|
74 // synchronization for receiving |
|
75 private final Object iMessageLock; |
|
76 |
|
77 private String iUri; |
|
78 |
|
79 // Application Id |
|
80 private String iAppID = null; |
|
81 |
|
82 // the listener used for messages receiving notifications |
|
83 private MessageListener iMessageListener; |
|
84 |
|
85 public MMSConnectionImpl(String aUri, boolean aServerConnection) |
|
86 throws IOException |
|
87 { |
|
88 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
89 "+ MMSConnectionImpl::MMSConnectionImpl()"); |
|
90 iUri = aUri; |
|
91 iState = INITIAL; |
|
92 iServerConnection = aServerConnection; |
|
93 // create the native side peer |
|
94 iNativeHandle = _createPeer(iServerConnection, iUri); |
|
95 iReadLock = new Object(); |
|
96 iWriteLock = new Object(); |
|
97 iCloseLock = new Object(); |
|
98 iMessageLock = new Object(); |
|
99 iSendLock = new Object(); |
|
100 // register for shutdown listening |
|
101 setShutdownListener(); |
|
102 if (iServerConnection) |
|
103 { |
|
104 iAppID = aUri.substring("mms://:".length()); |
|
105 } |
|
106 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
107 "- MMSConnectionImpl::MMSConnectionImpl()"); |
|
108 } |
|
109 |
|
110 /* |
|
111 * This function registers this object for shutDown. |
|
112 */ |
|
113 private void setShutdownListener() |
|
114 { |
|
115 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
116 "+ MMSConnectionImpl::setShutdownListener()"); |
|
117 // Get the insatnce of ApplicationUtils. |
|
118 ApplicationUtils appUtils = ApplicationUtils.getInstance(); |
|
119 |
|
120 // Get the name of the application. |
|
121 appUtils.addShutdownListener(new ShutdownListener() |
|
122 { |
|
123 //The method that gets called when Application is shutting down |
|
124 public void shuttingDown() |
|
125 { |
|
126 try |
|
127 { |
|
128 close(); |
|
129 } |
|
130 catch (IOException e) |
|
131 { |
|
132 //Nothing to do, just ignore |
|
133 Logger.LOG(Logger.EWMA, Logger.EInfo, e.toString()); |
|
134 } |
|
135 } |
|
136 }); |
|
137 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
138 "- MMSConnectionImpl::setShutdownListener()"); |
|
139 } |
|
140 |
|
141 /** |
|
142 * open() is only called when a MIDlet calls Connector.open() a MIDlet will |
|
143 * not be able to access the Connection until open() has completed and a |
|
144 * reference has been returned. It should then only be called once, by only |
|
145 * one thread. particularly, a Connection cannot be closed by a MIDlet until |
|
146 * it has been fully opened. |
|
147 */ |
|
148 public void open() |
|
149 { |
|
150 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
151 "+ MMSConnectionImpl::open()"); |
|
152 if (iState == INITIAL) |
|
153 { |
|
154 iState = OPEN; |
|
155 // in case of server connection a notifier thread is created which |
|
156 // waits in the native side and informs the application when there |
|
157 // is an incoming message. |
|
158 if (iServerConnection) |
|
159 { |
|
160 new Thread(new Runnable() |
|
161 { |
|
162 public void run() |
|
163 { |
|
164 _openConnection(iNativeHandle); |
|
165 } |
|
166 }).start(); |
|
167 } |
|
168 } |
|
169 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
170 "- MMSConnectionImpl::open()"); |
|
171 } |
|
172 |
|
173 /** |
|
174 * close() is only called when a MIDlet calls close() on a connection that |
|
175 * is opened by calling Connector.open(). A MIDlet will not be able to access |
|
176 * the Connection after calling close() on that connection. |
|
177 */ |
|
178 public void close() throws IOException |
|
179 { |
|
180 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
181 "+ MMSConnectionImpl::close()"); |
|
182 synchronized (iCloseLock) |
|
183 { |
|
184 if (iState != CLOSED) |
|
185 { |
|
186 iState = CLOSED; |
|
187 _closeConnection(iNativeHandle); |
|
188 // notify the notifier thread if it is waiting for a receive() |
|
189 // or setMessageListener() to be called |
|
190 synchronized (iMessageLock) |
|
191 { |
|
192 iMessageLock.notify(); |
|
193 } |
|
194 // notify the receive operation about connection closed |
|
195 synchronized (iReadLock) |
|
196 { |
|
197 iReadLock.notify(); |
|
198 } |
|
199 _dispose(iNativeHandle); |
|
200 } |
|
201 } |
|
202 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
203 "- MMSConnectionImpl::close()"); |
|
204 } |
|
205 |
|
206 /** |
|
207 * Returns the number of segments required for sending this Message. |
|
208 */ |
|
209 public int numberOfSegments(Message aMessage) |
|
210 { |
|
211 // For MMS numberOfSegments is always 1. |
|
212 return 1; |
|
213 } |
|
214 |
|
215 private int getMMSMaxSize() |
|
216 { |
|
217 return MmsPropertyRetriever.getMMSMaxSize(); |
|
218 } |
|
219 |
|
220 /** |
|
221 * Method for creating a Multipart Message object. If it is a client |
|
222 * connection The destination address of the newly created messages will be |
|
223 * set to the destination part of the URI provided when this connection was |
|
224 * created. |
|
225 * |
|
226 * @param aType |
|
227 * The type of the message to be created. It can only be |
|
228 * "Multipart" |
|
229 */ |
|
230 public Message newMessage(String aType) |
|
231 { |
|
232 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
233 "+ MMSConnectionImpl::newMessage()"); |
|
234 if (MessageConnection.MULTIPART_MESSAGE.equals(aType)) |
|
235 { |
|
236 if (iServerConnection) |
|
237 { |
|
238 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
239 "- MMSConnectionImpl::newMessage()"); |
|
240 return new MultipartMessageImpl(null, 0, getMMSMaxSize()); |
|
241 } |
|
242 else |
|
243 { |
|
244 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
245 "- MMSConnectionImpl::newMessage()"); |
|
246 return new MultipartMessageImpl(iUri, 0, getMMSMaxSize()); |
|
247 } |
|
248 } |
|
249 // unrecognized type |
|
250 throw new IllegalArgumentException( |
|
251 "Unrecognized message type: " + aType); |
|
252 } |
|
253 |
|
254 /** |
|
255 * Method for creating a Multipart Message object |
|
256 * |
|
257 * @param aType |
|
258 * The type of the message to be created. It can only be |
|
259 * "Multipart" |
|
260 * @param aAddress |
|
261 * the destination address of the Message |
|
262 */ |
|
263 public Message newMessage(String aType, String aAddress) |
|
264 { |
|
265 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
266 "+ MMSConnectionImpl::newMessage()"); |
|
267 if (MessageConnection.MULTIPART_MESSAGE.equals(aType)) |
|
268 { |
|
269 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
270 "- MMSConnectionImpl::newMessage()"); |
|
271 return new MultipartMessageImpl(aAddress, 0, getMMSMaxSize()); |
|
272 } |
|
273 // unrecognized type |
|
274 throw new IllegalArgumentException( |
|
275 "Unrecognized message type " + aType); |
|
276 |
|
277 } |
|
278 |
|
279 /** |
|
280 * Method for sending a certain message. Only Multipart Messages can be sent |
|
281 * through this connection. The Message to sent is validated before sending. |
|
282 * |
|
283 * @param aMsg |
|
284 * The message to be sent |
|
285 * @exceptions throws IOException if there is any n/w problem or if |
|
286 * connection is already closed |
|
287 * @exceptions throws InterruptedIOException if a timeout occurs or if the |
|
288 * connection is closed while sending. |
|
289 * @exceptions throws IllegalArguementException if any of the header field |
|
290 * is not specified |
|
291 */ |
|
292 public void send(Message aMsg) throws IOException, InterruptedIOException |
|
293 { |
|
294 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
295 "+ MMSConnectionImpl::send()"); |
|
296 // validate the message to be sent |
|
297 MultipartMessageImpl mMsg = validateMessage(aMsg); |
|
298 if (iServerConnection) |
|
299 { |
|
300 mMsg.setReplyToAppID(iAppID); |
|
301 } |
|
302 else |
|
303 { |
|
304 // validate the client-side message |
|
305 validateClientMessage(mMsg); |
|
306 } |
|
307 // Before sending the message serialize it |
|
308 byte[] bMsg = mMsg.serialize(); |
|
309 // to synchronize send functionality |
|
310 synchronized (iWriteLock) |
|
311 { |
|
312 synchronized (iSendLock) |
|
313 { |
|
314 // send operation should not be carried out while close is in |
|
315 // progress |
|
316 synchronized (iCloseLock) |
|
317 { |
|
318 if (iState == CLOSED) |
|
319 { |
|
320 throw new IOException("Sending message failed: " + |
|
321 ExceptionStrings.CONNECTION_CLOSED); |
|
322 } |
|
323 //checking for valid permissions |
|
324 ApplicationUtils appUtils = ApplicationUtils.getInstance(); |
|
325 MMSPermissionImpl permission = new MMSPermissionImpl( |
|
326 "mms://*", "send", |
|
327 getRecipientsCount(mMsg)); |
|
328 appUtils.checkPermission(permission); |
|
329 // send the message |
|
330 int status = _send(bMsg, 0, bMsg.length, mMsg.getAddress(), |
|
331 iNativeHandle); |
|
332 if (status < 0) |
|
333 { |
|
334 _checkError(status); |
|
335 } |
|
336 // wait till the message was sent successfully |
|
337 try |
|
338 { |
|
339 iSendLock.wait(); |
|
340 } |
|
341 catch (InterruptedException e) |
|
342 { |
|
343 Logger.ELOG(Logger.EWMA, "Message sending failed", e); |
|
344 } |
|
345 if (iSendError < 0) |
|
346 { |
|
347 _checkError(iSendError); |
|
348 } |
|
349 } |
|
350 } |
|
351 } |
|
352 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
353 "- MMSConnectionImpl::send()"); |
|
354 } |
|
355 |
|
356 /** |
|
357 * Callback through which the Native notifies about the sending of a Message |
|
358 * or any error while sending a message |
|
359 * |
|
360 * @param1 result the status of send operation |
|
361 */ |
|
362 protected void messageSentCallback(int aResult) |
|
363 { |
|
364 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
365 "+ MMSConnectionImpl::messageSentCallback()"); |
|
366 synchronized (iSendLock) |
|
367 { |
|
368 iSendError = aResult; |
|
369 iSendLock.notify(); |
|
370 } |
|
371 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
372 "- MMSConnectionImpl::messageSentCallback()"); |
|
373 } |
|
374 |
|
375 /** |
|
376 * Receive is a 3 step process: 1) Wait for some incoming message 2) |
|
377 * Retrieve the the message 3) Construct a Multipart Message |
|
378 * |
|
379 * @exceptions throws IOException if the connection is already closed. |
|
380 * @exceptions throws InterruptedIOException if the connection is closed |
|
381 * while receiving |
|
382 * @returns the constructed message |
|
383 */ |
|
384 synchronized public Message receive() throws IOException, |
|
385 InterruptedIOException |
|
386 { |
|
387 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
388 "+ MMSConnectionImpl::receive()"); |
|
389 if (!iServerConnection) |
|
390 { |
|
391 // Not Supported in Client MODE |
|
392 throw new IOException(ExceptionStrings.CLIENT_MODE); |
|
393 } |
|
394 Message rMsg; |
|
395 synchronized (iReadLock) |
|
396 { |
|
397 // check for connection |
|
398 if (iState == CLOSED) |
|
399 { |
|
400 throw new IOException("Receiving message failed: " + |
|
401 ExceptionStrings.CONNECTION_CLOSED); |
|
402 } |
|
403 // if no messages were there to receive wait till some message |
|
404 // arrives |
|
405 if (iMessagesOnQueue == 0) |
|
406 { |
|
407 iMessageWaiting =true; |
|
408 // notify the notifier thread |
|
409 synchronized (iMessageLock) |
|
410 { |
|
411 iMessageLock.notify(); |
|
412 } |
|
413 // wait for incoming message notification |
|
414 try |
|
415 { |
|
416 iReadLock.wait(); |
|
417 } |
|
418 catch (InterruptedException e) |
|
419 { |
|
420 Logger.ELOG(Logger.EWMA, "Message receiving failed", e); |
|
421 throw new InterruptedIOException(""); |
|
422 } |
|
423 } |
|
424 synchronized (iCloseLock) |
|
425 { |
|
426 //if the connection was closed throw InterruptedIOException |
|
427 if (iState == CLOSED) |
|
428 { |
|
429 throw new InterruptedIOException( |
|
430 "Connection closed while receiving message"); |
|
431 } |
|
432 //checking for valid permissions |
|
433 ApplicationUtils appUtils = ApplicationUtils.getInstance(); |
|
434 MMSPermissionImpl permission = new MMSPermissionImpl("mms://*", |
|
435 "receive"); |
|
436 appUtils.checkPermission(permission); |
|
437 |
|
438 byte[] msg = _retrieveMessage(iNativeHandle); |
|
439 rMsg = MultipartMessageImpl.deserialize(msg, getMMSMaxSize()); |
|
440 iMessagesOnQueue--; |
|
441 } |
|
442 } |
|
443 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
444 "- MMSConnectionImpl::receive()"); |
|
445 return rMsg; |
|
446 } |
|
447 |
|
448 /** |
|
449 * Sets the message listener for this connection |
|
450 * |
|
451 * @param aListener |
|
452 * listener interested for incoming message. |
|
453 * @exceptions throws IOException if the connection is already closed or |
|
454 * this method is called on a client connection. |
|
455 */ |
|
456 public void setMessageListener(MessageListener aListener) throws IOException |
|
457 { |
|
458 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
459 "+ MMSConnectionImpl::setMessageListener()"); |
|
460 if (!iServerConnection) |
|
461 { |
|
462 throw new IOException(ExceptionStrings.CLIENT_MODE); |
|
463 } |
|
464 if (iState == CLOSED) |
|
465 { |
|
466 throw new IOException("Setting message listener failed: " + |
|
467 ExceptionStrings.CONNECTION_CLOSED); |
|
468 } |
|
469 iMessageListener = aListener; |
|
470 if (iMessageListener != null) |
|
471 { |
|
472 synchronized (iMessageLock) |
|
473 { |
|
474 iMessageLock.notify(); |
|
475 } |
|
476 } |
|
477 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
478 "- MMSConnectionImpl::setMessageListener()"); |
|
479 } |
|
480 |
|
481 /** |
|
482 * Method that validates the message attributes |
|
483 * |
|
484 * @exceptions Throws IOException if any of the attribute is not valid |
|
485 */ |
|
486 private MultipartMessageImpl validateMessage(Message aMsg) |
|
487 throws IOException |
|
488 { |
|
489 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
490 "+ MMSConnectionImpl::validateMessage()"); |
|
491 // check against null |
|
492 if (null == aMsg) |
|
493 { |
|
494 throw new NullPointerException(ExceptionStrings.NULL_MESSAGE); |
|
495 } |
|
496 |
|
497 // make sure it is a MultipartMessageImpl |
|
498 MultipartMessageImpl mMsg; |
|
499 try |
|
500 { |
|
501 mMsg = (MultipartMessageImpl) aMsg; |
|
502 } |
|
503 catch (ClassCastException ex) |
|
504 { |
|
505 throw new IllegalArgumentException(ExceptionStrings. |
|
506 INVALID_MESSAGE_TYPE); |
|
507 } |
|
508 |
|
509 // check basic validation of the message and the corresponding parts |
|
510 if (!mMsg.iValidationDone) |
|
511 { |
|
512 // Forces the validation of the message if it hasn't been done |
|
513 // validation is done so that we reconstruct the message |
|
514 // with the eyes of the application and report any exceptions |
|
515 // to the application |
|
516 MultipartMessageImpl cloneMsg = new MultipartMessageImpl( |
|
517 mMsg.getDestinationAddress(), |
|
518 mMsg.getTimestamp() == null ? 0 : mMsg.getTimestamp().getTime(), |
|
519 MmsPropertyRetriever.getMMSMaxSize()); |
|
520 |
|
521 // first go through addresses and clone them for the new message |
|
522 cloneAddresses(MultipartMessageHeader.ADDRESS_TYPE_TO, cloneMsg, |
|
523 mMsg); |
|
524 cloneAddresses(MultipartMessageHeader.ADDRESS_TYPE_BCC, cloneMsg, |
|
525 mMsg); |
|
526 cloneAddresses(MultipartMessageHeader.ADDRESS_TYPE_CC, cloneMsg, |
|
527 mMsg); |
|
528 |
|
529 // clone the headers |
|
530 cloneMsg.setHeader(MultipartMessageHeader.DELIVERY_TIME_HEADER, |
|
531 mMsg.getHeader(MultipartMessageHeader.DELIVERY_TIME_HEADER)); |
|
532 cloneMsg.setHeader(MultipartMessageHeader.PRIORITY_HEADER, |
|
533 mMsg.getHeader(MultipartMessageHeader.PRIORITY_HEADER)); |
|
534 |
|
535 // clone the message parts |
|
536 cloneMessageParts(cloneMsg, mMsg); |
|
537 |
|
538 // clone the startContentId |
|
539 cloneMsg.setStartContentId(mMsg.getStartContentId()); |
|
540 |
|
541 // clone the subject |
|
542 cloneMsg.setSubject(mMsg.getSubject()); |
|
543 } |
|
544 |
|
545 // make sure there are recipients |
|
546 if (isEmpty(mMsg.getAddresses(MultipartMessageHeader.ADDRESS_TYPE_TO)) |
|
547 && isEmpty(mMsg.getAddresses(MultipartMessageHeader.ADDRESS_TYPE_BCC)) |
|
548 && isEmpty(mMsg.getAddresses(MultipartMessageHeader.ADDRESS_TYPE_CC))) |
|
549 { |
|
550 throw new IllegalArgumentException(ExceptionStrings.NO_RECIPIENTS); |
|
551 } |
|
552 |
|
553 if (mMsg.iReply) |
|
554 { |
|
555 // reset the delivery time |
|
556 mMsg.setHeader(MultipartMessageHeader.DELIVERY_TIME_HEADER, null); |
|
557 // if this message does not have the replyToAppid, it means it came |
|
558 // from a client connection and we can not reply |
|
559 if (mMsg.getReplyToAppID() == null ||(mMsg.getReplyToAppID() != null |
|
560 && (mMsg.getReplyToAppID().length() == 0 || mMsg.getReplyToAppID() |
|
561 .equals(MultipartMessageHeader.DUMMY_REPLY_TO_APP_ID)))) |
|
562 { |
|
563 throw new IllegalArgumentException(ExceptionStrings. |
|
564 CLIENT_MESSAGE); |
|
565 } |
|
566 String dest = mMsg.getAddress(); |
|
567 mMsg.removeAddresses(); |
|
568 // replace applicationID with replyToAppID |
|
569 mMsg.setAddress(dest); |
|
570 } |
|
571 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
572 "- MMSConnectionImpl::validateMessage()"); |
|
573 return mMsg; |
|
574 } |
|
575 |
|
576 private void cloneAddresses(String aAddressType, |
|
577 MultipartMessageImpl aDestMsg, MultipartMessageImpl aSourceMsg) |
|
578 { |
|
579 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
580 "+ MMSConnectionImpl::cloneAddresses()"); |
|
581 String[] addresses = aSourceMsg.getAddresses(aAddressType); |
|
582 if (addresses != null) |
|
583 { |
|
584 for (int i = 0; i < addresses.length; i++) |
|
585 { |
|
586 aDestMsg.addAddress(aAddressType, addresses[i]); |
|
587 } |
|
588 } |
|
589 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
590 "- MMSConnectionImpl::cloneAddresses()"); |
|
591 } |
|
592 |
|
593 private void cloneMessageParts(MultipartMessageImpl aDestMsg, |
|
594 MultipartMessageImpl aSourceMsg) throws SizeExceededException |
|
595 { |
|
596 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
597 "+ MMSConnectionImpl::cloneMessageParts()"); |
|
598 MessagePart[] parts = aSourceMsg.getMessageParts(); |
|
599 if (parts != null) |
|
600 { |
|
601 for (int i = 0; i < parts.length; i++) |
|
602 { |
|
603 MessagePart part = parts[i]; |
|
604 aDestMsg.addMessagePart(new MessagePart(part.getContent(), |
|
605 part.getMIMEType(), part.getContentID(), |
|
606 part.getContentLocation(), part.getEncoding())); |
|
607 } |
|
608 } |
|
609 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
610 "- MMSConnectionImpl::cloneMessageParts()"); |
|
611 } |
|
612 |
|
613 /** |
|
614 * Check that the address that has been provided when this connection was |
|
615 * created is still among the "to" recipients |
|
616 */ |
|
617 private void validateClientMessage(MultipartMessageImpl aMsg) |
|
618 { |
|
619 // sets the replyToAppID to its own iAppID |
|
620 aMsg.setReplyToAppID(MultipartMessageHeader.DUMMY_REPLY_TO_APP_ID); |
|
621 } |
|
622 |
|
623 /** |
|
624 * Method used for checking if there are no recipients set for * a message |
|
625 * to be set |
|
626 */ |
|
627 private boolean isEmpty(String[] aArray) |
|
628 { |
|
629 if (aArray == null || (aArray != null && aArray.length == 0)) |
|
630 { |
|
631 return true; |
|
632 } |
|
633 return false; |
|
634 } |
|
635 |
|
636 /** |
|
637 * Method that ensures whether a connection is opened |
|
638 * |
|
639 * @exceptions Throws IOException if the connection is in closed state |
|
640 */ |
|
641 private void ensureOpen() throws IOException |
|
642 { |
|
643 synchronized (iCloseLock) |
|
644 { |
|
645 if (iState == CLOSED) |
|
646 { |
|
647 throw new IOException(ExceptionStrings.CONNECTION_CLOSED); |
|
648 } |
|
649 } |
|
650 } |
|
651 |
|
652 /** |
|
653 * Callback through which the Native notifies about the receiving of a |
|
654 * Message or any error while receiving a message |
|
655 * |
|
656 * @param1 aReceivedMesgs - number of messages to be received |
|
657 * |
|
658 */ |
|
659 protected int messageReceiveCallback(int aReceivedMesgs) |
|
660 { |
|
661 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
662 "+ MMSConnectionImpl::messageReceiveCallback()"); |
|
663 synchronized (iMessageLock) |
|
664 { |
|
665 if ((!iMessageWaiting) && (null == iMessageListener)) |
|
666 { |
|
667 try |
|
668 { |
|
669 iMessageLock.wait(); |
|
670 } |
|
671 catch (InterruptedException e) |
|
672 { |
|
673 Logger.ELOG(Logger.EWMA, "Receiving a callback failed", e); |
|
674 } |
|
675 } |
|
676 } |
|
677 synchronized (iReadLock) |
|
678 { |
|
679 if (aReceivedMesgs >= 0) |
|
680 { |
|
681 iMessagesOnQueue += aReceivedMesgs; |
|
682 iNotificationsToMake += aReceivedMesgs; |
|
683 } |
|
684 if (iMessageWaiting) |
|
685 { |
|
686 iMessageWaiting = false; |
|
687 //if a receive operation was called notify the receive about |
|
688 //the incoming message |
|
689 iReadLock.notify(); |
|
690 |
|
691 } |
|
692 else if (iMessageListener != null) |
|
693 { |
|
694 while (iNotificationsToMake > 0) |
|
695 { |
|
696 iMessageListener.notifyIncomingMessage(this); |
|
697 iNotificationsToMake--; |
|
698 } |
|
699 } |
|
700 } |
|
701 Logger.LOG(Logger.EWMA, Logger.EInfo, |
|
702 "- MMSConnectionImpl::messageReceiveCallback()"); |
|
703 return ((iState == CLOSED)? -1 : 0); |
|
704 } |
|
705 |
|
706 private int getRecipientsCount(MultipartMessageImpl mMsg) |
|
707 { |
|
708 int cnt = 0; |
|
709 String[] tmp = mMsg.getAddresses( |
|
710 MultipartMessageHeader.ADDRESS_TYPE_TO); |
|
711 if (tmp != null) |
|
712 { |
|
713 cnt += tmp.length; |
|
714 } |
|
715 tmp = mMsg.getAddresses( |
|
716 MultipartMessageHeader.ADDRESS_TYPE_CC); |
|
717 if (tmp != null) |
|
718 { |
|
719 cnt += tmp.length; |
|
720 } |
|
721 tmp = mMsg.getAddresses( |
|
722 MultipartMessageHeader.ADDRESS_TYPE_BCC); |
|
723 if (tmp != null) |
|
724 { |
|
725 cnt += tmp.length; |
|
726 } |
|
727 return cnt; |
|
728 } |
|
729 |
|
730 private native int _createPeer(boolean aServerConnection, String aUri); |
|
731 |
|
732 private native void _openConnection(int aNativeHandle); |
|
733 |
|
734 private native int _send(byte[] aMsg, int aOffset, int aMsgLength, |
|
735 String aAddress, int aNativeHandle); |
|
736 |
|
737 private native byte[] _retrieveMessage(int aNativeHandle); |
|
738 |
|
739 private native void _closeConnection(int aNativeHandle); |
|
740 |
|
741 private native void _dispose(int aNativeHandle); |
|
742 |
|
743 private native void _checkError(int aError); |
|
744 } |
|
745 |
|
746 |