/*
* Copyright (C) 2007-2008 Esmertec AG. Copyright (C) 2007-2008 The Android Open
* Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package info.guardianproject.otr.app.im.engine;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import android.content.Context;
/**
* An <code>ImConnection</code> is an abstract representation of a connection to
* the IM server.
*/
public abstract class ImConnection {
/** Connection state that indicates the connection is not connected yet. */
public static final int DISCONNECTED = 0;
/** Connection state that indicates the user is logging into the server. */
public static final int LOGGING_IN = 1;
/** Connection state that indicates the user has logged into the server. */
public static final int LOGGED_IN = 2;
/** Connection state that indicates the user is logging out the server. */
public static final int LOGGING_OUT = 3;
/** Connection state that indicate the connection is suspending. */
public static final int SUSPENDING = 4;
/** Connection state that indicate the connection has been suspended. */
public static final int SUSPENDED = 5;
/** The capability of supporting group chat. */
public static final int CAPABILITY_GROUP_CHAT = 1;
/** The capability of supporting session re-establishment. */
public static final int CAPABILITY_SESSION_REESTABLISHMENT = 2;
/** The current state of the connection. */
protected int mState;
protected CopyOnWriteArrayList<ConnectionListener> mConnectionListeners;
protected Presence mUserPresence;
protected Context mContext;
protected ImConnection(Context context) {
mConnectionListeners = new CopyOnWriteArrayList<ConnectionListener>();
mState = DISCONNECTED;
mContext = context;
}
public void addConnectionListener(ConnectionListener listener) {
if (listener != null) {
mConnectionListeners.add(listener);
}
}
public void removeConnectionListener(ConnectionListener listener) {
mConnectionListeners.remove(listener);
}
public abstract Contact getLoginUser();
public String getLoginUserName() {
Contact loginUser = getLoginUser();
return loginUser == null ? null : loginUser.getName();
}
public abstract int[] getSupportedPresenceStatus();
public Presence getUserPresence() {
if (mState == SUSPENDING || mState == SUSPENDED) {
return new Presence();
}
if (mState != LOGGED_IN) {
// In most cases we have a valid mUserPresence instance also
// in the LOGGING_OUT state. However there is one exception:
// if logout() is called before login finishes, the state may
// jump from LOGGING_IN directly to LOGGING_OUT, skipping the
// LOGGED_IN state. In this case we won't have a valid Presence
// in the LOGGING_OUT state.
return null;
}
return new Presence(mUserPresence);
}
public abstract void initUser (long providerId, long accountId) throws ImException;
public void updateUserPresenceAsync(Presence newPresence) throws ImException {
if (mState != LOGGED_IN) {
throw new ImException(ImErrorInfo.NOT_LOGGED_IN, "NOT logged in");
}
doUpdateUserPresenceAsync(newPresence);
}
/**
* Tells the engine that the network type has changed, e.g. switch from gprs
* to wifi. The engine should drop all the network connections created
* before because they are not available anymore.
*
* The engine might also need to redo authentication on the new network
* depending on the underlying protocol.
*/
public void networkTypeChanged() {
}
/** Tells the current state of the connection. */
public int getState() {
return mState;
}
/**
* Sets the state of the connection.
*
* @param state the new state of the connection.
* @param error the error information which caused the state change or null.
*/
protected void setState(int state, ImErrorInfo error) {
if (state < DISCONNECTED || state > SUSPENDED) {
throw new IllegalArgumentException("Invalid state: " + state);
}
if (mState != state) {
mState = state;
for (ConnectionListener listener : mConnectionListeners) {
listener.onStateChanged(state, error);
}
}
}
protected void notifyUserPresenceUpdated() {
for (ConnectionListener listener : mConnectionListeners) {
listener.onUserPresenceUpdated();
}
}
protected void notifyUpdateUserPresenceError(ImErrorInfo error) {
for (ConnectionListener listener : mConnectionListeners) {
listener.onUpdatePresenceError(error);
}
}
/**
* Gets bit-or of capabilities supported by the underlying protocol. Valid
* capability bits are: {@value #CAPABILITY_GROUP_CHAT},
* {@value #CAPABILITY_SESSION_REESTABLISHMENT}
*
* @return bit-or of capabilities supported by the underlying protocol
*/
public abstract int getCapability();
/**
* Log in to the IM server, using the settings stored in Imps.
*
* @param accountId the ID to get the Account record
* @param passwordTemp a one time use password, not to be saved
* @param providerId the ID to get the ProviderSettings record
* @param retry whether or not to retry the connection upon failure
*/
public abstract void loginAsync(long accountId, String passwordTemp, long providerId,
boolean retry);
/**
* Re-establish previous session using the session context persisted by the
* client. Only sessions that were dropped unexpectedly(e.g. power loss,
* crash, etc) can be re-established using the stored session context. If
* the session was terminated normally by either user logging out or server
* initiated disconnection, it can't be re-established again therefore the
* stored context should be removed by the client. <p> The client can query
* if session re-establishment is supported through {@link #getCapability()}
* .
*
* @param sessionContext the session context which was fetched from previous
* session by {@link #getSessionContext()} and persisted by the
* client.
* @throws UnsupportedOperationException if session re-establishment is not
* supported by the underlying protocol.
*/
public abstract void reestablishSessionAsync(Map<String, String> sessionContext);
/** Log out from the IM server. */
public abstract void logoutAsync();
/** Immediate logout */
public abstract void logout();
/** Suspend connection with the IM server. */
public abstract void suspend();
/**
* Gets the cookie of the current session. The client could store the
* context and use it to re-establish the session by
* {@link #reestablishSessionAsync(Map)} . The stored context MUST be
* removed upon the connection logout/disconnect.
*
* @return the context of the current session or <code>null</code> if the
* user has not logged in yet.
* @throws UnsupportedOperationException if session re-establishment is not
* supported by the underlying protocol.
*/
public abstract Map<String, String> getSessionContext();
/**
* Gets the instance of ChatSessionManager for the connection.
*
* @return the instance of ChatSessionManager for the connection.
*/
public abstract ChatSessionManager getChatSessionManager();
/**
* Gets the instance of ContactListManager for the connection.
*
* @return the instance of ContactListManager for the connection.
*/
public abstract ContactListManager getContactListManager();
/**
* Gets the instance of ChatGroupManager for the connection.
*
* @return the instance of ChatGroupManager for the connection.
* @throws UnsupportedOperationException if group chat is not supported by
* the underlying protocol.
*/
public abstract ChatGroupManager getChatGroupManager();
/**
* Whether this connection is going over Tor or not.
* @return boolean
*/
public abstract boolean isUsingTor();
protected abstract void doUpdateUserPresenceAsync(Presence presence);
/**
* Handle a heartbeat.
*
* @param heartbeatInterval the number of heartbeats before a ping should be sent.
*/
public abstract void sendHeartbeat(long heartbeatInterval);
public abstract void setProxy(String type, String host, int port);
}