| /* |
| * 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 com.android.im.imps; |
| |
| import java.util.HashMap; |
| |
| import com.android.im.engine.ImErrorInfo; |
| import com.android.im.imps.Primitive.TransactionMode; |
| |
| public class ImpsTransactionManager { |
| private ImpsConnection mConnection; |
| private int mTransactionId; |
| |
| /** Keep track of the client initialized transactions. */ |
| private HashMap<String, AsyncTransaction> mClientTransactions; |
| |
| private HashMap<String, ServerTransactionListener> mServerTransactionListeners; |
| |
| /** |
| * Constructs an instance of transaction manager. |
| */ |
| ImpsTransactionManager(ImpsConnection connection) { |
| this.mConnection = connection; |
| mClientTransactions = new HashMap<String, AsyncTransaction>(); |
| mServerTransactionListeners = new HashMap<String, ServerTransactionListener>(); |
| } |
| |
| /** |
| * Sets a ServerTransactionListener on this manager so that it will be |
| * notified when a specified transaction has been initialized by the server. |
| * |
| * @param type the primitive type of the transaction. |
| * @param listener the ServerTransactionListener to be notified, or |
| * <code>null</code> to clear the listener on specified type. |
| */ |
| public void setTransactionListener(String type, ServerTransactionListener listener) { |
| synchronized(mServerTransactionListeners) { |
| if (listener == null) { |
| mServerTransactionListeners.remove(type); |
| } else { |
| mServerTransactionListeners.put(type, listener); |
| } |
| } |
| } |
| |
| /** |
| * Originates an async transaction from the client. |
| * @param tx |
| */ |
| void beginClientTransaction(AsyncTransaction tx) { |
| synchronized(mClientTransactions) { |
| tx.setTransactionInfo(nextTransactionId(), mConnection); |
| mClientTransactions.put(tx.getId(), tx); |
| } |
| } |
| |
| /** |
| * Terminates a transaction which was originated from the client. |
| * |
| * @param tx the transaction to terminate. |
| */ |
| void endClientTransaction(AsyncTransaction tx) { |
| synchronized(mClientTransactions) { |
| mClientTransactions.remove(tx.getId()); |
| } |
| } |
| |
| void reassignTransactionId(Primitive p) { |
| synchronized (mClientTransactions) { |
| AsyncTransaction tx = mClientTransactions.remove(p.getTransactionID()); |
| if(tx != null) { |
| String newId = nextTransactionId(); |
| tx.setTransactionInfo(newId, mConnection); |
| p.setTransactionId(newId); |
| mClientTransactions.put(newId, tx); |
| } |
| } |
| } |
| |
| /** |
| * TODO: This should not be called from the DataChannel thread. |
| * |
| * @param transactionId |
| * @param code |
| * @param info |
| */ |
| public void notifyErrorResponse(String transactionId, |
| int code, String info) { |
| AsyncTransaction tx; |
| synchronized(mClientTransactions) { |
| tx = mClientTransactions.get(transactionId); |
| } |
| if (tx != null) { |
| tx.notifyError(new ImErrorInfo(code, info)); |
| } else { |
| ImpsLog.log("Ignoring possible server transaction error " + code + info); |
| } |
| } |
| |
| /** |
| * Notifies the TransactionManager that a new primitive from the server has |
| * arrived. |
| * |
| * @param primitive the incoming primitive. |
| */ |
| public void notifyIncomingPrimitive(Primitive primitive) { |
| String transactionId = primitive.getTransactionID(); |
| if (primitive.getTransactionMode() == TransactionMode.Response) { |
| |
| AsyncTransaction tx; |
| synchronized(mClientTransactions) { |
| tx = mClientTransactions.get(transactionId); |
| } |
| // The transaction might has been terminated by the client, |
| // just ignore the incoming primitive in that case. |
| if (tx != null) { |
| tx.notifyResponse(primitive); |
| } |
| } else { |
| ServerTransaction serverTx = new ServerTransaction(transactionId, |
| mConnection, primitive); |
| |
| ServerTransactionListener listener; |
| synchronized(mServerTransactionListeners) { |
| listener = mServerTransactionListeners.get(primitive.getType()); |
| } |
| if (listener != null) { |
| listener.notifyServerTransaction(serverTx); |
| } else { |
| ImpsLog.log("Unhandled Server transaction: " + primitive.getType()); |
| } |
| } |
| } |
| |
| /** |
| * Generates a new transaction ID. |
| * |
| * @return a new transaction ID. |
| */ |
| private synchronized String nextTransactionId() { |
| if(mTransactionId >= 999) { |
| mTransactionId = 0; |
| } |
| return String.valueOf(++mTransactionId); |
| } |
| |
| } |