Home | History | Annotate | Download | only in engine
      1 /*
      2  * Copyright (C) 2007-2008 Esmertec AG.
      3  * Copyright (C) 2007-2008 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package com.android.im.engine;
     19 
     20 import java.util.HashMap;
     21 import java.util.concurrent.CopyOnWriteArrayList;
     22 
     23 /**
     24  * An <code>ImConnection</code> is an abstract representation of a connection
     25  * to the IM server.
     26  */
     27 public abstract class ImConnection {
     28     /**
     29      * Connection state that indicates the connection is not connected yet.
     30      */
     31     public static final int DISCONNECTED = 0;
     32 
     33     /**
     34      * Connection state that indicates the user is logging into the server.
     35      */
     36     public static final int LOGGING_IN = 1;
     37 
     38     /**
     39      * Connection state that indicates the user has logged into the server.
     40      */
     41     public static final int LOGGED_IN = 2;
     42 
     43     /**
     44      * Connection state that indicates the user is logging out the server.
     45      */
     46     public static final int LOGGING_OUT = 3;
     47 
     48     /**
     49      * Connection state that indicate the connection is suspending.
     50      */
     51     public static final int SUSPENDING = 4;
     52 
     53     /**
     54      * Connection state that indicate the connection has been suspended.
     55      */
     56     public static final int SUSPENDED = 5;
     57 
     58     /**
     59      * The capability of supporting group chat.
     60      */
     61     public static final int CAPABILITY_GROUP_CHAT = 1;
     62     /**
     63      * The capability of supporting session re-establishment.
     64      */
     65     public static final int CAPABILITY_SESSION_REESTABLISHMENT = 2;
     66 
     67     /**
     68      * The current state of the connection.
     69      */
     70     protected int mState;
     71 
     72     protected CopyOnWriteArrayList<ConnectionListener> mConnectionListeners;
     73     protected Presence mUserPresence;
     74 
     75     protected ImConnection() {
     76         mConnectionListeners = new CopyOnWriteArrayList<ConnectionListener>();
     77         mState = DISCONNECTED;
     78     }
     79 
     80     public void addConnectionListener(ConnectionListener listener) {
     81         if (listener != null) {
     82             mConnectionListeners.add(listener);
     83         }
     84     }
     85 
     86     public void removeConnectionListener(ConnectionListener listener) {
     87         mConnectionListeners.remove(listener);
     88     }
     89 
     90     public abstract Contact getLoginUser();
     91 
     92     public String getLoginUserName() {
     93         Contact loginUser = getLoginUser();
     94         return loginUser == null ? null : loginUser.getName();
     95     }
     96 
     97     public abstract int[] getSupportedPresenceStatus();
     98 
     99     public Presence getUserPresence() {
    100         if (mState == SUSPENDING || mState == SUSPENDED) {
    101             return new Presence();
    102         }
    103 
    104         if (mState != LOGGED_IN) {
    105             // In most cases we have a valid mUserPresence instance also
    106             // in the LOGGING_OUT state. However there is one exception:
    107             // if logout() is called before login finishes, the state may
    108             // jump from LOGGING_IN directly to LOGGING_OUT, skipping the
    109             // LOGGED_IN state. In this case we won't have a valid Presence
    110             // in the LOGGING_OUT state.
    111             return null;
    112         }
    113 
    114         return new Presence(mUserPresence);
    115     }
    116 
    117     public void updateUserPresenceAsync(Presence newPresence) throws ImException {
    118         if (mState != LOGGED_IN) {
    119             throw new ImException(ImErrorInfo.NOT_LOGGED_IN, "NOT logged in");
    120         }
    121 
    122         doUpdateUserPresenceAsync(newPresence);
    123     }
    124 
    125     /**
    126      * Tells the engine that the network type has changed, e.g. switch from gprs
    127      * to wifi. The engine should drop all the network connections created before
    128      * because they are not available anymore.
    129      *
    130      * The engine might also need to redo authentication on the new network depending
    131      * on the underlying protocol.
    132      */
    133     public void networkTypeChanged(){
    134     }
    135 
    136     /**
    137      * Tells the current state of the connection.
    138      */
    139     public int getState() {
    140         return mState;
    141     }
    142 
    143     /**
    144      * Sets the state of the connection.
    145      *
    146      * @param state the new state of the connection.
    147      * @param error the error information which caused the state change or null.
    148      */
    149     protected void setState(int state, ImErrorInfo error) {
    150         if(state < DISCONNECTED || state > SUSPENDED){
    151             throw new IllegalArgumentException("Invalid state: " + state);
    152         }
    153         if(mState != state){
    154             mState = state;
    155             for(ConnectionListener listener : mConnectionListeners){
    156                 listener.onStateChanged(state, error);
    157             }
    158         }
    159     }
    160 
    161     protected void notifyUserPresenceUpdated() {
    162         for (ConnectionListener listener : mConnectionListeners) {
    163             listener.onUserPresenceUpdated();
    164         }
    165     }
    166 
    167     protected void notifyUpdateUserPresenceError(ImErrorInfo error) {
    168         for (ConnectionListener listener : mConnectionListeners) {
    169             listener.onUpdatePresenceError(error);
    170         }
    171     }
    172 
    173     /**
    174      * Gets bit-or of capabilities supported by the underlying protocol. Valid
    175      * capability bits are: {@value #CAPABILITY_GROUP_CHAT},
    176      * {@value #CAPABILITY_SESSION_REESTABLISHMENT}
    177      *
    178      * @return bit-or of capabilities supported by the underlying protocol
    179      */
    180     public abstract int getCapability();
    181 
    182     /**
    183      * Log in to the IM server.
    184      *
    185      * @param loginInfo the login information.
    186      */
    187     public abstract void loginAsync(LoginInfo loginInfo);
    188 
    189     /**
    190      * Re-establish previous session using the session context persisted by the
    191      * client. Only sessions that were dropped unexpectedly(e.g. power loss, crash,
    192      * etc) can be re-established using the stored session context. If the
    193      * session was terminated normally by either user logging out or server
    194      * initiated disconnection, it can't be re-established again therefore the
    195      * stored context should be removed by the client.
    196      * <p>
    197      * The client can query if session re-establishment is supported through
    198      * {@link #getCapability()}.
    199      *
    200      * @param sessionContext
    201      *            the session context which was fetched from previous session by
    202      *            {@link #getSessionContext()} and persisted by the client.
    203      * @throws UnsupportedOperationException
    204      *             if session re-establishment is not supported by the
    205      *             underlying protocol.
    206      */
    207     public abstract void reestablishSessionAsync(HashMap<String, String> sessionContext);
    208 
    209     /**
    210      * Log out from the IM server.
    211      */
    212     public abstract void logoutAsync();
    213 
    214     /**
    215      * Suspend connection with the IM server.
    216      */
    217     public abstract void suspend();
    218 
    219     /**
    220      * Gets the cookie of the current session. The client could store the
    221      * context and use it to re-establish the session by
    222      * {@link #reestablishSessionAsync(HashMap)}}. The stored context MUST be
    223      * removed upon the connection logout/disconnect.
    224      *
    225      * @return the context of the current session or <code>null</code> if the
    226      *         user has not logged in yet.
    227      * @throws UnsupportedOperationException
    228      *             if session re-establishment is not supported by the
    229      *             underlying protocol.
    230      */
    231     public abstract HashMap<String, String> getSessionContext();
    232 
    233     /**
    234      * Gets the instance of ChatSessionManager for the connection.
    235      *
    236      * @return the instance of ChatSessionManager for the connection.
    237      */
    238     public abstract ChatSessionManager getChatSessionManager();
    239 
    240     /**
    241      * Gets the instance of ContactListManager for the connection.
    242      *
    243      * @return the instance of ContactListManager for the connection.
    244      */
    245     public abstract ContactListManager getContactListManager();
    246 
    247     /**
    248      * Gets the instance of ChatGroupManager for the connection.
    249      *
    250      * @return the instance of ChatGroupManager for the connection.
    251      * @throws UnsupportedOperationException
    252      *             if group chat is not supported by the underlying protocol.
    253      */
    254     public abstract ChatGroupManager getChatGroupManager();
    255 
    256     protected abstract void doUpdateUserPresenceAsync(Presence presence);
    257 
    258 }
    259