[Webfunds-commits] java/webfunds/client/sox SOXWallet.java

Ian Grigg iang@cypherpunks.ai
Sun, 16 Jul 2000 15:31:36 -0400 (AST)


iang        00/07/16 15:31:36

  Modified:    webfunds/client/sox SOXWallet.java
  Log:
  1. cleaned up some old RuntimeExs into Panics.
  2. added idempotent Id for DepositRequest.
  3. cleaned up unused code in doDeposit (a lot).
  4. made doDeposit quiet (except for update).
  5. added high level quiet cancel call for Teller.

Revision  Changes    Path
1.129     +195 -122  java/webfunds/client/sox/SOXWallet.java

Index: SOXWallet.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/client/sox/SOXWallet.java,v
retrieving revision 1.128
retrieving revision 1.129
diff -u -r1.128 -r1.129
--- SOXWallet.java	2000/07/14 00:02:31	1.128
+++ SOXWallet.java	2000/07/16 19:31:35	1.129
@@ -1,4 +1,4 @@
-/* $Id: SOXWallet.java,v 1.128 2000/07/14 00:02:31 iang Exp $
+/* $Id: SOXWallet.java,v 1.129 2000/07/16 19:31:35 iang Exp $
  *
  * Copyright (c) Systemics Inc. 1995-2000 on behalf of
  * The WebFunds Development Team.  All Rights Reserved.
@@ -37,6 +37,8 @@
 import webfunds.sox.Payment;
 import webfunds.sox.Receipt;
 import webfunds.sox.SOXAccountException;
+import webfunds.sox.SOXArgsException;
+import webfunds.sox.SOXDepositException;
 import webfunds.sox.SOXException;
 import webfunds.sox.SOXLaterException;
 import webfunds.sox.SOXPacketException;
@@ -144,7 +146,7 @@
         {
             String e = "Error reading stores\n" + ex;
             logmsg(e);
-            throw new RuntimeException(e);
+            throw new Panic(e);
         }
     }
 
@@ -794,7 +796,7 @@
 
         MailItem[] mails;
         try {
-            mails = sub.deposit(pay, new String(desc));
+            mails = sub.deposit(pay, new String(desc), null);
         } catch (SOXLaterException ex) {
             error(try_again_later);
             return ;
@@ -901,92 +903,91 @@
 
 
     /**
-     * Deposit the given payment.
+     *  Deposit the given payment.
+     *  Method for sophisticated Wallet users (Teller, etc) should not use GUI.
      *
-     * If the Payment is a bearer payment it is deposited in targetAccount.
-     * If not, targetAccount must be null.
-     *
-     * If the Payment 
-     */
-    public Receipt doDeposit(
-        Payment payment, 
-        AccountId accountToUse, 
-        byte[] desc)
-    throws DepositException
+     *  @param payment for deposit
+     *  @param account is the account to use
+     *  @param desc description
+     *  @param idempotentId is suggested id for deposit, ignored if null/empty
+     */
+    public Receipt doDeposit(Payment payment, AccountId account, 
+                             byte[] desc, String idempotentId)
+        throws DepositException
     {
         ENTER("doDeposit");
         TRACE("payment="  + payment  + 
-            ", accountToUse=" + accountToUse + 
-            ", desc="     + desc     );
+            ", account=" + account+ 
+            ", desc   ="     + desc     );
 
         Payment pay = payment;
-
-        AccountId ptt = pay.getTarget();
-        AccountId pss = pay.getSource();
-
-        AccountInfo callerAc=new AccountInfo(accountToUse.getId(), null, null);
-        AccountInfo ps      =new AccountInfo(pss.getId(), null, null);
-        AccountInfo pt      =new AccountInfo(ptt.getId(), null, null);
-
-        String pid = pay.getId();
-
-
-        //
-        //  Acquire the account which does the deposit.
-        //  This might not be a participant in the activity.
-        //  Which makes it terribly complex.
-        //  Maybe this should be banned, or another flexible
-        //  interface provided.
-        //
         Account ac;
-        boolean knownAccount = true;  // following code should work, except...
-        try
-        {
-            if (pt.isBearer())
-            {
-                System.err.println("it's a bearer payment!");
-                // Ok, so it's bearer, and we can deposit it anywhere.
-                ac = getAccount(callerAc);
-
-                if (ac == null)
-                    throw new RuntimeException("no target for bearer");
-
-                // this is who we are going to deposit the bearer into
-                ptt = ac.getId();
-                pt = new AccountInfo(ptt.getId(), null, this);
-                knownAccount = true;
-            }
-            else
-            {
-                System.err.println("JCvG: it's not a bearer payment");
-                //
-                //  We need to acquire an account, so as to get a
-                //  subaccount, so as to do a deposit.  It doesn't
-                //  actually make much difference which sub account
-                //  does the deposit, as the issuer checks that the
-                //  payment is good, not the deposit (unless bearer).
-                //  But, it's nice for the receipt if it is all
-                //  aligned.
-                //
- // was this back to front?  Should look at target first...
-                ac = getAccount(ps);
-                if (ac == null)                      // not our target
-                {
-                    ac = getAccount(pt);
-                    if(ac == null)
-                        throw new DepositException(
-                            DepositException.UNKNOWN_ACCOUNT);
-                }
-            }
-        }
-        catch (StoreException ex)
-        {
-            ex.printStackTrace();
-            error("cannot recover accounts? " + ex);
-            throw new RuntimeException("Dunno, looks very wrong");
+        try {
+            ac = getAccount(account);
+        } catch (StoreException ex) {
+            ex.printStackTrace(System.err);
+            throw new Panic("cannot get account " + account +
+                            " payment " + payment + "\n" + ex);
         }
 
+//        AccountId ptt = pay.getTarget();
+//        AccountId pss = pay.getSource();
+//
+//
+//        //
+//        //  Acquire the account which does the deposit.
+//        //  This might not be a participant in the activity.
+//        //  Which makes it terribly complex.
+//        //  Maybe this should be banned, or another flexible
+//        //  interface provided.
+//        //
+//        Account ac;
+//        boolean knownAccount = true;  // following code should work, except...
+//        try
+//        {
+//            if (ptt.isBearer())
+//            {
+//                System.err.println("it's a bearer payment!");
+//                // Ok, so it's bearer, and we can deposit it anywhere.
+//                ac = getAccount(accountToUse);
+//
+//                if (ac == null)
+//                    throw new Panic("no target for bearer");
+//
+//                // this is who we are going to deposit the bearer into
+//                ptt = ac.getId();
+//                //pt = new AccountInfo(ptt.getId(), null, this);
+//                knownAccount = true;
+//            }
+//            else
+//            {
+//                System.err.println("JCvG: it's not a bearer payment");
+//                //
+//                //  We need to acquire an account, so as to get a
+//                //  subaccount, so as to do a deposit.  It doesn't
+//                //  actually make much difference which sub account
+//                //  does the deposit, as the issuer checks that the
+//                //  payment is good, not the deposit (unless bearer).
+//                //  But, it's nice for the receipt if it is all
+//                //  aligned.
+//                //
+// // was this back to front?  Should look at target first...
+//                ac = getAccount(pss);
+//                if (ac == null)                      // not our target
+//                {
+//                    ac = getAccount(ptt);
+//                    if(ac == null)
+//                        throw new DepositException(
+//                            DepositException.UNKNOWN_ACCOUNT);
+//                }
+//            }
+//        }
+//        catch (StoreException ex)
+//        {
+//            throw new Panic("cannot recover accounts? " + ex);
+//        }
 
+
         String choice = ac.getName();
         logmsg("ready to deposit payment using " + choice + "\n" + pay);
         if (desc == null)
@@ -1007,25 +1008,31 @@
                 ac.newSub(sub);
             } catch (SOXSubAccountException ex) {
                 ex.printStackTrace();
-                error("cannot create SubAccount: " + ex);
-                throw new RuntimeException("cannot create subAccount");
+                throw new Panic("cannot create subAccount: " + ex);
             } catch (SOXAccountException ex) {
                 ex.printStackTrace();
-                error("Account error: " + ex);
-                throw new RuntimeException("Account error: " + ex);
+                throw new Panic("Account error: " + ex);
             }
         }
 
         MailItem[] mails;
         try {
-            mails = sub.deposit(pay, new String(desc));
+            mails = sub.deposit(pay, new String(desc), idempotentId);
+
+        } catch (SOXDepositException ex) {      // webfunds.sox.Errors
+            throw new DepositException(ex.getNumber(), ex.getMessage());
         } catch (SOXLaterException ex) {
-            throw new RuntimeException("later!");
-        } catch (SOXSubAccountException e) {
-            e.printStackTrace();
-            throw new DepositException(e.getNumber());
+            throw new DepositException(ex.getNumber(), ex.getMessage());
+        } catch (SOXSubAccountException ex) {   // negative
+            ex.printStackTrace();
+            throw new DepositException(ex.getNumber(), ex.getMessage());
+
+        } catch (SOXArgsException ex) {
+            ex.printStackTrace();
+            throw new Panic("args failed: " + ex);
         } catch (SOXException ex) {
-            throw new DepositException(DepositException.INSUFFICIENT_FUNDS);
+            ex.printStackTrace();
+            throw new Panic("unknown exception: " + ex);
         }
 
         logmsg("received mails: " + mails.length);
@@ -1037,56 +1044,61 @@
         //  (Actually, as implemented, there is only one mail.)
         //
         if (mails == null)
-            throw new RuntimeException(
+            throw new Panic(
                 "Deposit partial (no mail returned) try an update...");
 
-        String s = checkReceipt(mails[0], pss, ptt, item, pay.getQty());
+        AccountId ptt = pay.getTarget();
+        AccountId pss = pay.getSource();
+        long qty = pay.getQty();
+        String s = checkReceipt(mails[0], pss, ptt, item, qty);
         if (s != null)
-            throw new RuntimeException("cancel receipt is not good: " + s);
+            /// hmmm this is really a SubAccount failure, should never happen
+            throw new DepositException(SOXSubAccountException.NO_RECEIPT);
 
-        if (makeNewSub && !knownAccount)      // only if our account...
-        {
-            // I think this is right.
-            aviso("Deposit is complete.\n\nAs the account is unknown,\nignoring mail and subs");
-            throw new RuntimeException("Account unknown???");
-        }
+//        if (makeNewSub && !knownAccount)      // only if our account...
+//        {
+//            // I think this is right.
+//            aviso("Deposit is complete.\n\nAs the account is unknown,\nignoring mail and subs");
+//            throw new Panic("Account unknown???");
+//        }
 
         String statString = "";
         //
-        // Some admin
+        //  Some admin
         //       - make a new sub by re-adding the account if needed.
         //       - get a name for a new source account.
         //
         if (makeNewSub)
         {
             //
-            // The getSub() did all the account work,
-            // now just need to store it.
+            //  The getSub() did all the account work,
+            //  now just need to (re)store it.
             //
             try {
                 accountStore.addAccount(ac);
             } catch (StoreException ex) {
                 ex.printStackTrace(System.err);
-                logmsg("account " + ac + " sub " + sub);
-                logmsg("cannot add subaccount? " + ex);
-                System.exit(1);
+                throw new Panic("cannot add subaccount " + sub +
+                                " to account " + ac + "\n" + ex);
             }
-            aviso("Hmmm.  That worked, and created a new subaccount...\n" +
-                  "which you can't see :(  What you need is a workaround:" +
-                  "\n\nTo see the contract, hit [Add Contract] on this:" +
-                  "\n\n" + item + "\n\n" +
-                  "(as there is no way to tell the GUI what to do here!)");
-            statString += "\n    (subAccount made in " + ac + ")";
+//            aviso("Hmmm.  That worked, and created a new subaccount...\n" +
+//                  "which you can't see :(  What you need is a workaround:" +
+//                  "\n\nTo see the contract, hit [Add Contract] on this:" +
+//                  "\n\n" + item + "\n\n" +
+//                  "(as there is no way to tell the GUI what to do here!)");
+//            statString += "\n    (subAccount made in " + ac + ")";
         }
 
 
+        // damn this is noisy
         internalUpdate(sub, mails);
 
         Receipt rcpt = mailItemToReceipt( mails[0] );
         if( rcpt == null )
-            throw new DepositException(DepositException.NO_RECEIPT);
-        else
-            return rcpt;
+            /// hmmm this is really a SubAccount failure, should never happen
+            throw new DepositException(SOXSubAccountException.NO_RECEIPT);
+
+        return rcpt;
     }
 
 
@@ -1235,14 +1247,39 @@
 
     /**
      *  Cancel a Payment (pid) within a SubAccount.
+     *  And call the update.  For high-level user programs.
+     */
+    public void cancel(AccountId account, ItemId item, String pid)
+        throws CancelException, SOXLaterException
+    {
+
+        Account ac;
+        try {
+            ac = getAccount(account);
+        } catch (StoreException ex) {
+            logmsg("store cannot deliver account: " + ex);
+            throw new CancelException(CancelException.UNKNOWN_AC,
+                                      ex.getMessage());
+        }
+
+        SubAccount sub = ac.getSub(item);
+        if (sub == null)
+            throw new CancelException(CancelException.UNKNOWN_SUB);
+        if (!(sub instanceof ValueAccount))
+            throw new CancelException(CancelException.NOT_VALUE);
+            
+
+        internalCancel((ValueAccount)sub, pid);
+    }
+
+    /**
+     *  Cancel a Payment (pid) within a SubAccount.
      *  And call the update.  This can be used by other wallets.
      *  If an error occurs, an error box is popped up.
      */
     protected void cancel(ValueAccount sub, String pid)
     {
 
-        // AccountId acct = new AccountId();
-        // acct.setId(info.getId());
         String e = null;
         try {
             internalCancel(sub, pid);
@@ -1263,13 +1300,13 @@
      *  @return a StateReceipt, or null if the pid is not found
      */
     public StateReceipt getTransactionState(AccountId acct,
-                                ItemId item, String pid)
+                                ItemId item, String id)
     {
         StateReceipt sr;
         try {
-            sr = receiptStore.getReceipt(acct, item, pid);
+            sr = receiptStore.getReceipt(acct, item, id);
         } catch (StoreException ex) {
-            throw new webfunds.utils.Panic("get StateReceipt for " + pid);
+            throw new webfunds.utils.Panic("get StateReceipt for " + id);
         }
         return sr ;
     }
@@ -1418,14 +1455,15 @@
      */
     protected void quietCancel(ValueAccount sub, String[] pids)
     {
-        throw new RuntimeException("not implemented");
+        throw new Panic("not implemented");
     }
 
 
     /**
      *  Cancel a Payment (pid) within a SubAccount.
      *  This can be used by other wallets, but be
-     *  careful to complete the update.
+     *  careful to complete the update and store by calling
+     *  internalUpdate(SubAccount, MailItem[])
      *
      *  @return Mails received, first of which is the applicable one
      */
@@ -1810,6 +1848,9 @@
      *  Get and sign for the mail from the issuer for this account.
      *  Will drag in all items that are handled by this account at
      *  this issuer - part of the account request structure.
+     *
+     *  @param accountinfo is the application-level account descriptor
+     *
      *  Client Wallet Interface
      */
     public void update(AccountInfo accountinfo, ItemId item)
@@ -1821,10 +1862,42 @@
             account = getAccount(accountinfo);
         } catch (StoreException ex) {
             ex.printStackTrace();
-            error("update: " + ex);
+            error("update " + accountinfo + ": " + ex);
             return ;
         }
 
+        update(account, item);
+    }
+
+    /**
+     *  Get and sign for the mail from the issuer for this account.
+     *  Will drag in all items that are handled by this account at
+     *  this issuer - part of the account request structure.
+     */
+    public void update(AccountId accountId, ItemId item)
+    {
+        logmsg("AccountId update");
+        Account account;
+        try {
+            account = getAccount(accountId);
+        } catch (StoreException ex) {
+            ex.printStackTrace();
+            throw new Panic("update id " + accountId + ": " + ex);
+        }
+
+        update(account, item);
+    }
+
+
+    /**
+     *  Get and sign for the mail from the issuer for this account.
+     *  Will drag in all items that are handled by this account at
+     *  this issuer - part of the account request structure.
+     */
+    protected void update(Account account, ItemId item)
+    {
+        logmsg("update");
+
         //
         // Before we grab the subaccount, check if it exists.
         //
@@ -1923,7 +1996,7 @@
                 return ;
         }
 
-        throw new RuntimeException("too many: mail appears to be spinning");
+        throw new Panic("too many: mail appears to be spinning");
     }