
/**
 * AccountsImpl.java
 *
 *
 * Created: Thu Jul 29 17:36:35 1999
 *
 * @author Jan Newmarch
 * @version 1.0
 */

package txn;

// import common.Accounts;
import net.jini.core.transaction.server.TransactionManager;
import net.jini.core.transaction.server.TransactionParticipant;
import net.jini.core.transaction.server.TransactionConstants;
import java.rmi.server.UnicastRemoteObject;
import java.util.Hashtable;
// import java.rmi.RMISecurityManager;
// debug
import net.jini.core.lookup.ServiceTemplate;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.discovery.LookupLocator;
// end debug

public class AccountsImpl extends UnicastRemoteObject 
    implements RemoteAccounts, TransactionParticipant, java.io.Serializable {
    
    protected long crashCount = 0; // value??
    protected Hashtable accountBalances = new Hashtable();
    protected Hashtable pendingCreditDebit = new Hashtable();

    public AccountsImpl() throws java.rmi.RemoteException {
	// System.setSecurityManager(new RMISecurityManager());	
    }

    public void creditDebit(long amount, long creditorID,
			    long debitorID, long transactionID,
			    TransactionManager mgr) {
	
	// Ensure stub class is loaded by getting its class object.
	// It has to be loaded from the same place as this object
	java.rmi.Remote stub = null;
	try {
	    stub = toStub(this);
	} catch(Exception e) {
	    System.out.println("To stub failed");
	    e.printStackTrace();
	}
	System.out.println("To stub found");
	String annote = java.rmi.server.RMIClassLoader.getClassAnnotation(stub.getClass());
	System.out.println("from " + annote);
	try {
	    Class cl = java.rmi.server.RMIClassLoader.loadClass(annote, "txn.AccountsImpl_Stub");
	} catch(Exception e) {
	    System.out.println("To stub class failed");
	    e.printStackTrace();
	}
	System.out.println("To stub class ok");

	// mgr = findManager();
	try {
	    System.out.println("Trying to join");
	    mgr.join(transactionID, this, crashCount);
	} catch(net.jini.core.transaction.UnknownTransactionException e) {
	    e.printStackTrace();
	} catch(java.rmi.RemoteException e) {
	    e.printStackTrace();
	} catch(net.jini.core.transaction.server.CrashCountException e) {
	    e.printStackTrace();
	} catch(net.jini.core.transaction.CannotJoinException e) {
	    e.printStackTrace();
	}
	System.out.println("joined");
	pendingCreditDebit.put(new TransactionPair(mgr, 
						   transactionID),
			       new CreditDebit(amount, creditorID,
					       debitorID));
    }

    // findmanager debug hack
    protected TransactionManager findManager() {
	// find a known account service
        LookupLocator lookup = null;
        ServiceRegistrar registrar = null;
	TransactionManager mgr = null;

        try {
            lookup = new LookupLocator("jini://localhost");
        } catch(java.net.MalformedURLException e) {
            System.err.println("Lookup failed: " + e.toString());
            System.exit(1);
        }

        try {
            registrar = lookup.getRegistrar();
        } catch (java.io.IOException e) {
            System.err.println("Registrar search failed: " + e.toString());
            System.exit(1);
        } catch (java.lang.ClassNotFoundException e) {
            System.err.println("Registrar search failed: " + e.toString());
            System.exit(1);
        }
        System.out.println("Registrar found");

	Class[] classes = new Class[] {TransactionManager.class};
	ServiceTemplate template = new ServiceTemplate(null, classes, 
                                                   null);
	try {
	    mgr = (TransactionManager) registrar.lookup(template);
	} catch(java.rmi.RemoteException e) {
	    System.exit(2);
	}
	return mgr;
    }

    public int prepare(TransactionManager mgr, long id) {
	System.out.println("Preparing...");
	return TransactionConstants.PREPARED;
    }

    public void commit(TransactionManager mgr, long id) {
	System.out.println("committing");

    }


    public void abort(TransactionManager mgr, long id) {
	System.out.println("aborting");
    }

    public int prepareAndCommit(TransactionManager mgr, long id) {
	int result = prepare(mgr, id);
	if (result == TransactionConstants.PREPARED) {
	    commit(mgr, id);
	    result = TransactionConstants.COMMITTED;
	}
	return result;
    }

    class CreditDebit {
	long amount;
	long creditorID;
	long debitorID;

	CreditDebit(long a, long c, long d) {
	    amount = a;
	    creditorID = c;
	    debitorID = d;
	}
    }

    class TransactionPair {

	TransactionPair(TransactionManager mgr, long id) {

	}
    }
} // AccountsImpl






