javaextensions/wma/sms_cbs/javasrc/com/nokia/mj/impl/sms/SMSConnectionImpl.java
changeset 21 2a9601315dfc
child 78 71ad690e91f5
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     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