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