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

Ian Grigg iang@cypherpunks.ai
Sat, 24 Mar 2001 12:25:42 -0400 (AST)


iang        01/03/24 12:25:42

  Modified:    webfunds/client/sox SOXWallet.java
  Log:
  Lots of little cuts to help the separation from high level (WWI)
  to low level (LLW) wallets.
  
     1. removed getAccounts2(), replaced with getAccountIds() for LLW
     2. made many apparently internal call protected not public
     3. added existsAccount() and existsSubAccount() methods for LLW
     4. added getContractIds() for LLW
     5. made update(AccountId, ItemId) bypass noisy code, now is LLW,
        and added companion quietUpdate() that doesn't throw Ex
     6. tidied up doco to identify LLW and WWI calls.
  
  The interfaces (if not the code) may now be ready to separate.

Revision  Changes    Path
1.148     +272 -104  java/webfunds/client/sox/SOXWallet.java

Index: SOXWallet.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/client/sox/SOXWallet.java,v
retrieving revision 1.147
retrieving revision 1.148
diff -u -r1.147 -r1.148
--- SOXWallet.java	2001/03/23 15:06:02	1.147
+++ SOXWallet.java	2001/03/24 16:25:41	1.148
@@ -1,4 +1,4 @@
-/* $Id: SOXWallet.java,v 1.147 2001/03/23 15:06:02 iang Exp $
+/* $Id: SOXWallet.java,v 1.148 2001/03/24 16:25:41 iang Exp $
  *
  * Copyright (c) Systemics Inc. 1995-2000 on behalf of
  * The WebFunds Development Team.  All Rights Reserved.
@@ -69,15 +69,18 @@
 
 
 /**
- *  The GUI Wallet.
+ *  The WebFunds GUI SOX Wallet.
  *
- *  Needs to be rewritten into 2 wallets, a highlevel WebFunds GUI
- *  wallet and a low level SOX wallet that returns all info internally.
+ *  Needs to be rewritten into 2 wallets: a high level
  *
- *  See quiteCancel for example of low call.  It should not use AccountInfo
- *  (artifact of Receipt Store).
+ *        "WebFunds Wallet Interface" is high level, GUI
+ *  and 
+ *        "Low Level Wallet Interface" is low level, SOX, quiet
+ *        uses SOX objects / nothing from webfunds.client
  *
- * @version $Revision: 1.147 $
+ *  Check the above search strings for separation so far.
+ *
+ * @version $Revision: 1.148 $
  */
 public class SOXWallet
     extends Debug
@@ -370,7 +373,7 @@
     /**
      *  Shutdown signal or similar.
      *
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      */
     public int adminEvent(int code, String reason)
     {
@@ -401,7 +404,7 @@
 /////////  Acquire Things  //////////////////////////////
 
     /**
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      */
     public long getValue(AccountInfo info, ItemId contract, boolean pending)
     {
@@ -432,7 +435,7 @@
      * Call this one if you know the account is there,
      * and you don't want to handle the exception.
      */
-    public Account getAccountOrDie(AccountId id)
+    protected Account getAccountOrDie(AccountId id)
     {
         Account acct = null;
         try {
@@ -449,28 +452,52 @@
     /**
      * Call this one if you know the account is there,
      * and you don't want to handle the exception.
+     */
+    protected Account getAccountOrDie(AccountInfo info)
+    {
+        AccountId id = getAccountId(info);
+        return getAccountOrDie(id);
+    }
+
+    /**
+     *  @return true if the account exists, else false
      */
-    public Account getAccountOrDie(AccountInfo info)
+    public boolean existsAccount(AccountId id)
     {
         Account acct = null;
         try {
-            acct = getAccount(info);
+            acct = getAccount(id);
         } catch (StoreException ex) {
-            ex.printStackTrace(System.err);
-            logmsg("account " + info);
-            logmsg("no such account? " + ex);
-            System.exit(1);
+            return false;
         }
-        return acct ;
+        return true;
+    }
+
+    /**
+     *  @return true if the account and contract exists, else false
+     */
+    public boolean existsSubAccount(AccountId id, ItemId contractid)
+    {
+        Account acct = null;
+        try {
+            acct = getAccount(id);
+        } catch (StoreException ex) {
+            return false;
+        }
+
+        if (acct.subExists(contractid))
+            return true;
+
+        return false;
     }
 
-    public Account getAccount(AccountId id)
+    protected Account getAccount(AccountId id)
         throws StoreException
     {
         return accountStore.getAccount(id) ;
     }
 
-    public Account getAccount(AccountInfo info)
+    protected Account getAccount(AccountInfo info)
         throws StoreException
     {
         return accountStore.getAccount(getAccountId(info)) ;
@@ -486,8 +513,12 @@
         return acct;
     }
 
+    /**
+     *  WebFunds Wallet Interface
+     */
     public AccountInfo[] getAccounts()
     {
+/*
         Account[] accounts;
         try {
             accounts = accountStore.getAllAccounts();
@@ -500,16 +531,20 @@
         if (accounts == null)
             return new AccountInfo[0];
 logmsg("Retrieved " + accounts.length + " accounts");
+*/
+
+        AccountId[] ids = getAccountIds();
+        int len = ids.length;
 
         Addressbook ad = context.getAddressbook(this);
-        AccountInfo[] acInfos = new AccountInfo[accounts.length];
+        AccountInfo[] acInfos = new AccountInfo[len];
         boolean failed = false;
 
-        for (int i = 0; i < accounts.length; i++)
+        for (int i = 0; i < len; i++)
         {
             try
             {
-                byte[] rawName = accounts[i].getId().getByteArray();
+                byte[] rawName = ids[i].getByteArray();
                 AccountInfo info = ad.getInfo(rawName);
                 info.setWalletInterface(this);
                 acInfos[i] = info;
@@ -532,33 +567,72 @@
     }
 
 
-    public Account[] getAccounts2()
+    /**
+     *  Get a list of accounts managed by this wallet.
+     *
+     *  Low Level Wallet Interface
+     *
+     *  @return an array of all AccountIds, maybe empty but never null
+     */
+    public AccountId[] getAccountIds()
     {
-        try
-        {
-            return this.accountStore.getAllAccounts();
+        Account[] accounts;
+        try {
+            accounts = accountStore.getAllAccounts();
+        } catch (StoreException ex) {
+            ex.printStackTrace();
+            error("Store is bad: " + ex);
+            return new AccountId[0];
         }
-        catch(Exception e)
+
+        if (accounts == null)
+            return new AccountId[0];
+        int len = accounts.length;
+logmsg("Retrieved " + len + " accounts");
+
+        AccountId[] ids = new AccountId[len];
+
+        for (int i = 0; i < len; i++)
         {
-            throw new Panic("Cannot obtain accounts :-(");
+            ids[i] = accounts[i].getId();
         }
+        return ids;
     }
 
 
+    /**
+     *  Get the contract identifiers for the stated account.
+     *
+     *  Low Level Wallet Interface.
+     */
+    public ItemId[] getContractIds(AccountId accountid)
+        throws StoreException
+    {
+        Account acct = getAccount(accountid);
+
+        ItemId[] items = acct.getItemIds();
+        logmsg("Ac " + acct + " : " + items.length + " items!");
+        for (int i = 0; i < items.length; i++)
+            logmsg("      " + items[i]);
+        return items;
+    }
+
+    /**
+     *  Get the contract identifiers for the stated account.
+     *
+     *  WebFunds Wallet Interface.
+     */
     public ItemId[] getContracts(AccountInfo account)
     {
-        Account acct;
+        ItemId[] items;
+        AccountId id = getAccountId(account);
+
         try {
-            acct = getAccount(account);
+            items = getContractIds(id);
         } catch (StoreException ex) {
             error("StoreException: " + ex);
             return null;
         }
-
-        ItemId[] items = acct.getItemIds();
-        logmsg("Ac " + account + " : " + items.length + " items!");
-        for (int i = 0; i < items.length; i++)
-            logmsg("      " + items[i]);
         return items;
     }
 
@@ -571,10 +645,10 @@
      *  Also updates the addressbook.
      *  Should targetinfo be an AccountInfo?  We don't really know of it.
      *
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      */
-    public byte[] makePayment(ItemId contractid, AccountInfo source,
-                              AccountInfo targetinfo,
+    public byte[] makePayment(ItemId contractid,
+                              AccountInfo source, AccountInfo targetinfo,
                               long amount, byte[] desc,
                               Date from, Date till)
     {
@@ -789,7 +863,8 @@
      * @param till the time at which the payment will expire
      * @param pid a payment identifier, ignored if empty
      */
-    public synchronized Payment makeSafePayment(AccountId src, AccountId tgt,
+    public synchronized AbstractPayment makeSafePayment(
+                              AccountId src, AccountId tgt,
                               ItemId contractid, long amount,
                               byte[] desc,
                               long from, long till,
@@ -1173,7 +1248,8 @@
     /**
      *  Make an ASCII-armoured message from a payment,
      *  a la PGP armouring.  Filters out exceptions.
-     *  Low level wallet.
+     *
+     *  Low Level Wallet Interface.
      */
     public byte[] asciiArmour(AbstractPayment pay)
         throws PaymentException
@@ -1198,7 +1274,8 @@
 
     /**
      *  Make an ASCII-armoured message from a payment, a la PGP armouring.
-     *  High level wallet.
+     *
+     *  For WebFunds Wallet.
      */
     public byte[] asciiArmourWithError(AbstractPayment pay)
     {
@@ -1255,7 +1332,7 @@
     /**
      *  Do a deposit.
      *
-     *  High level wallet.
+     *  WebFunds Wallet Interface.
      */
     public void makeDeposit(byte[] payBuf, AccountInfo callerAc, byte[] desc)
     {
@@ -1550,6 +1627,8 @@
      *  Deposit the given payment.
      *  Method for sophisticated Wallet users (Teller, etc) should not use GUI.
      *
+     *  Low Level Wallet Interface
+     *
      *  @param pay for deposit
      *  @param account is the account to use
      *  @param desc description
@@ -1596,7 +1675,7 @@
         ValueAccount sub = (ValueAccount) ac.getSub(item);
         if (sub == null)
         {
-            makeNewSub = true;              // only if our account...
+            makeNewSub = true;
             logmsg("no sub " + item.fp() + " in " + ac.fp() + ", making...");
             sub = new ValueAccount(item);
             try {
@@ -1650,14 +1729,6 @@
             /// 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 Panic("Account unknown???");
-//        }
-
-        String statString = "";
         //
         //  Some admin
         //       - make a new sub by re-adding the account if needed.
@@ -1668,6 +1739,8 @@
             //
             //  The getSub() did all the account work,
             //  now just need to (re)store it.
+            //  As this is a low level call, caller already checked
+            //  whether the deposit was appropriate.
             //
             try {
                 accountStore.addAccount(ac);
@@ -1676,16 +1749,9 @@
                 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 + ")";
         }
 
 
-        // damn this is noisy
         internalUpdate(sub, mails);
 
         Receipt rcpt = mailItemToReceipt( mails[0] );
@@ -1786,7 +1852,7 @@
      *  interface into SOX, and SOX needs to batch these up
      *  similarly.  Tricky.
      *
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      */
     public void cancel(Transaction[] trans)
     {
@@ -1797,7 +1863,7 @@
     /**
      *  Cancel a Transaction.
      *
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      */
     public void cancel(Transaction trans)
     {
@@ -1850,6 +1916,8 @@
     /**
      *  Cancel a Payment (pid) within a SubAccount.
      *  And call the update.  For high-level user programs.
+     *
+     *  Low Level Wallet Interface
      */
     public void cancel(AccountId account, ItemId item, String pid)
         throws CancelException, SOXLaterException
@@ -1896,7 +1964,9 @@
 
 
     /**
-     *  Low level wallet method to return the state for a transaction.
+     *  Return the full state (machine) for a transaction.
+     *
+     *  Low Level Wallet Interface
      *
      *  @return a StateReceipt, or null if the pid is not found
      */
@@ -1915,6 +1985,8 @@
     /**
      *  Cancel Payments (by pids) within a SubAccount
      *  before they hit the server.
+     *
+     *  Is quiet.
      */
     protected void internalCancel(ValueAccount sub, String[] pids)
         throws CancelException, SOXLaterException
@@ -1997,7 +2069,7 @@
             //  should not try and force the update?  Still have
             //  to do something with the mails.
             //
-            internalUpdate(sub, confirms);    // damn this is not quiet!
+            internalUpdate(sub, confirms);
             errors = "updated " + num + " mails.\n" + errors;
         }
 
@@ -2047,7 +2119,7 @@
         //  should not try and force the update?  Still have
         //  to do something with the mails.
         //
-        internalUpdate(sub, mails);    // damn this is not quiet!
+        internalUpdate(sub, mails);
 
         return ;
     }
@@ -2057,6 +2129,8 @@
      *  Cancel many Payments (pid) within a SubAccount.
      *  Not yet used, more here as a placeholder.
      *
+     *  Low Level Wallet Interface
+     *
      *  @return an error string if errors detected, else empty (never null)
      */
     protected void quietCancel(ValueAccount sub, String[] pids)
@@ -2071,6 +2145,8 @@
      *  careful to complete the update and store by calling
      *  internalUpdate(SubAccount, MailItem[])
      *
+     *  Low Level Wallet Interface
+     *
      *  @return Mails received, first of which is the applicable one
      */
     protected MailItem[] quietCancel(ValueAccount sub, String pid)
@@ -2127,10 +2203,12 @@
     /**
      * Create a new account in the Wallet and return it's AccountId.
      *
+     *  Who uses this?  Internal?
+     *
      * This method either returns a valid AccountId or throws an exception,
      * it never returns null. Argument 'name' may be null.
      */
-    public AccountId createAccount(String name) throws WalletException {
+    protected AccountId createAccount(String name) throws WalletException {
 
         if( this.isClosed() )
             throw new WalletException(WalletException.CLOSED);
@@ -2159,7 +2237,7 @@
 
 
     /**
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      */
     public AccountInfo addAccount()
     {
@@ -2168,9 +2246,10 @@
             return null ;
         }
 
+        String q = "Please specify a name for this account: ";
+        String newAccName = context.getUInterface(this).getInput(q);
+
         try {
-            String q = "Please specify a name for this account: ";
-            String newAccName = context.getUInterface(this).getInput(q);
 
             AccountId newAccId = this.createAccount(newAccName);
             AccountInfo newAccInfo = 
@@ -2202,7 +2281,7 @@
      *  the address book.  It's being polite by telling us, so we can
      *  keep it all consistent.
      *
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      */
     public boolean renameAccount(AccountInfo accountinfo, String name)
     {
@@ -2238,7 +2317,7 @@
     }
 
     /**
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      */
     public boolean removeAccount(AccountInfo accountinfo)
     {
@@ -2290,7 +2369,7 @@
     }
 
     /**
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      */
     public boolean removeContract(AccountInfo accountinfo, ItemId item)
     {
@@ -2412,7 +2491,7 @@
         String sorry = "\n\n\n" +
                      "To completely remove all traces, the receipts\n" +
                      "would have to be removed from the receipt store.\n\n\n" +
-                     "Er, sorry.  I don't know how to do that :(\n";
+                     "(Not implemented in this version.)\n";
         aviso("Subaccount removed." + sorry);
 
         return true;
@@ -2422,7 +2501,7 @@
     /**
      *  Adds the contract to the Account.
      *
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      *
      *  @return the itemId of the contract (even when already added),
      *          or null on failure
@@ -2509,7 +2588,7 @@
      *
      *  @param accountinfo is the application-level account descriptor
      *
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      */
     public void update(AccountInfo accountinfo, ItemId item)
     {
@@ -2527,30 +2606,14 @@
         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.
+     *
+     *  Intended for WebFunds wallet - noisy call.
      */
     protected void update(Account account, ItemId item)
     {
@@ -2565,8 +2628,26 @@
             return ;
         }
         SubAccount sub = account.getSub(item);
+
+        //
+        //  Do the sub.update, which sends all cached hashes,
+        //  and returns more receipts.
+        //
+        try
+        {
+            manyUpdates(sub, null);       // sub is surrogate for account
+        } 
+        catch (SOXLaterException e)
+        {
+            // Moved here where a popup is ok.
 
-        manyUpdates(sub, null);           // sub is surrogate for account
+            error(try_again_later);
+        } catch (SOXSubAccountException e) {
+            error("update failed (SubAccount broken?) :\n    " + e);
+        } catch (SOXException e) {
+            e.printStackTrace();
+            error("update failed: " + e);
+        }
     }
 
 
@@ -2593,19 +2674,103 @@
         return ac.getId();
     }
 
+    /**
+     *  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.
+     *
+     *  Low Level Wallet Interface
+     *
+     *  The account must exist.
+     *
+     *  @throw SOXLaterException if the backend is down
+     *  @throw SOXSubAccountException if the account has experienced a problem,
+     *         or if the item is not found in the account
+     */
+    public void update(AccountId accountId, ItemId item)
+        throws SOXLaterException, SOXSubAccountException
+    {
+        logmsg("AccountId update");
+        Account account;
+        try {
+            account = getAccount(accountId);
+        } catch (StoreException ex) {
+            ex.printStackTrace();
+            throw new Panic("update id " + accountId + ": " + ex);
+        }
 
+        //
+        // Before we grab the subaccount, check if it exists.
+        //
+        if (!account.subExists(item))
+            throw new SOXSubAccountException("contract not added?  " + item);
+
+        SubAccount sub = account.getSub(item);
+
+        //
+        //  Do the sub.update, which sends all cached hashes,
+        //  and returns more receipts.
+        //
+        try
+        {
+            manyUpdates(sub, null);       // sub is surrogate for account
+
+        } catch (SOXException e) {
+            e.printStackTrace();
+            logmsg("update failed: " + e);
+        }
+
+    }
+
     /**
-     *  Handle this mail that came via another request
+     *  Get and sign for the mail from the issuer for this account
+     *  and Item.
+     *  Will drag in all items that are handled by this account at
+     *  this issuer - part of the account request structure.
+     *
+     *  Low Level Wallet Interface
+     */
+    public void quietUpdate(AccountId accountId, ItemId item)
+    {
+        //
+        //  Do the sub.update, which sends all cached hashes,
+        //  and returns more receipts.
+        //
+        try
+        {
+            update(accountId, item);       // sub is surrogate for account
+
+        } catch (SOXSubAccountException e) {
+            logmsg("update failed (SubAccount broken?) :\n    " + e);
+        } catch (SOXLaterException e) {
+            logmsg("Later:    " + e);
+        } catch (SOXException e) {
+            e.printStackTrace();
+            logmsg("update failed: " + e);
+        }
+
+    }
+
+
+    /**
+     *  Handle these mails that came via another request
      *  or another subaccount.
      *  The subaccount must identify the account and the SOXServer.
      *  All mail items must come from the same SOXServer,
      *  (but are not necessarily the same subaccount, etc).
      *  This points to a flaw in the sox object model.
+     *
+     *  Low Level Wallet Interface - quiet call.
      */
     protected void internalUpdate(SubAccount sub, MailItem[] mails)
     {
-        // AccountInfo info = getAccountInfo(sub);
-        manyUpdates(sub, mails);
+        try {
+            manyUpdates(sub, mails);
+        } catch (SOXLaterException ex) {
+            logmsg("try mail later!");
+        } catch (SOXException ex) {
+            logmsg("SOXEx: " + ex);
+        }
     }
 
 
@@ -2613,7 +2778,7 @@
     {
         MailItem[] mm = new MailItem[1];
         mm[0] = mail;
-        manyUpdates(sub, mm);
+        internalUpdate(sub, mm);
     }
 
 
@@ -2621,6 +2786,7 @@
      * Get and sign for the mail from the issuer for this account.
      */
     protected void manyUpdates(SubAccount sub, MailItem[] mails)
+        throws SOXLaterException, SOXException
     {
         if (isClosed())
         {
@@ -2646,7 +2812,9 @@
         //
         for (int i = 0; i < 10; i++)
         {
-            mails = tryUpdate(sub, confirms);
+            // mails = tryUpdate(sub, confirms);
+            mails = sub.update(confirms);
+
             if (mails == null || (mails.length == 0))
                 return ;
             logmsg("for(;" + i + "<4; ++) on " + mails.length + " mails");
@@ -2676,7 +2844,6 @@
      *  the sub is simply passed here as an active sub from
      *  which we can do the request to the Issuer, the item
      *  of the sub forms no part of the data.
-     */
     protected MailItem[] tryUpdate(SubAccount sub, MailId[] confirms)
     {
         MailItem[] mails;
@@ -2707,6 +2874,7 @@
 
         return mails ;
     }
+     */
 
 
     /**
@@ -2751,7 +2919,7 @@
      *         so we can extend, and call super() on this method.
      *         throw a save-fail exception?
      */
-    public boolean handleMail(MailItem mail, SubAccount sub)
+    protected boolean handleMail(MailItem mail, SubAccount sub)
     {
         boolean ok = false;
 
@@ -2768,7 +2936,7 @@
     /**
      *  For some reason, Receipts are stored on an account basis.
      */
-    public boolean handleReceiptData(byte[] recdata, AccountId acct)
+    protected boolean handleReceiptData(byte[] recdata, AccountId acct)
     {
         Receipt rec = null;
         try {
@@ -2784,7 +2952,7 @@
     }
 
 
-    public boolean handleReceipt(Receipt rec, AccountId acct)
+    protected boolean handleReceipt(Receipt rec, AccountId acct)
     {
         try {
             receiptStore.addReceipt(rec, acct);
@@ -2797,13 +2965,13 @@
         return true ;        // got it stored, please confirm
     }
 
-    public void confirm(Vector v, byte[] b)
+    protected void confirm(Vector v, byte[] b)
     {
         v.addElement(MailId.newInstance(b));
 
     }
 
-    public void confirm(Vector v, MailItem mi)
+    protected void confirm(Vector v, MailItem mi)
     {
         v.addElement(mi.getMailId());
     }
@@ -2817,7 +2985,7 @@
      *  Internally to this wallet, we have Receipts and PendingReceipts.
      *  Latter needs to be collected and converted into Transactions.
      *
-     *  Client Wallet Interface
+     *  WebFunds Wallet Interface
      *
      *  @return a list of Transactions within this subaccount
      */