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

Ian Grigg iang@cypherpunks.ai
Sun, 24 Sep 2000 19:19:11 -0400 (AST)


iang        00/09/24 19:19:11

  Modified:    webfunds/client AccountBrowserImpl.java Core.java
                        WalletInterface.java
               webfunds/client/sox SOXWallet.java WalletException.java
  Log:
  1. added an admin event method to wallets so that shutdown could be
     attempted.  this is an experimental method for which I needed the
     interface in place before writing the usage code...
  2. moved all backups stuff into webfunds.client.utils.Backup, also
     see new Startup object.

Revision  Changes    Path
1.76      +53 -50    java/webfunds/client/AccountBrowserImpl.java

Index: AccountBrowserImpl.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/client/AccountBrowserImpl.java,v
retrieving revision 1.75
retrieving revision 1.76
diff -u -r1.75 -r1.76
--- AccountBrowserImpl.java	2000/09/18 17:02:26	1.75
+++ AccountBrowserImpl.java	2000/09/24 23:19:09	1.76
@@ -1,5 +1,5 @@
 /*
- * $Id: AccountBrowserImpl.java,v 1.75 2000/09/18 17:02:26 iang Exp $
+ * $Id: AccountBrowserImpl.java,v 1.76 2000/09/24 23:19:09 iang Exp $
  *
  * Copyright (c) Systemics Inc 1999 on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
@@ -325,6 +325,14 @@
         tree.expandPath(new TreePath(node.getPath()));
     }
 
+    protected void sendAdminEvent(int code, String reason)
+    {
+        logmsg("ADMIN EVENT! ");
+        for (int i = 0; i < wallets.length; i++)
+            wallets[i].adminEvent(code, reason);
+    }
+
+
     //
     //  These are added as standard, and also added for custom wallet
     //  plugin popups.
@@ -358,62 +366,54 @@
           }
         };
 
-        //
-        //  Do a backup to a user-selected directory.
-        //
+        /**
+         *  Do a backup to a user-selected directory.
+         */
         Action backupaction = new AbstractAction("Backup")
         {
           public void actionPerformed(ActionEvent evt)
           {
-            JFileChooser fc = new JFileChooser();
-            fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
-            fc.setDialogTitle("Select Directory where you wish to Backup " +
-                              me + " into");
-
-            //
-            //  Make a directory.  If we fail to make, keep trying!
-            //
-            boolean ok = false;
-            File targetDir = null;
-            while (!ok)
-            {
-                int res = fc.showDialog(new JFrame(), "Select Backup Dir");
-                if (res != JFileChooser.APPROVE_OPTION)
-                    return ;
+            sendAdminEvent(SOXWallet.CODE_FREEZE, "backup being conducted");
+            File srcDir = new File(".");
+            webfunds.client.utils.Backup.backup(ui, srcDir);
+            sendAdminEvent(SOXWallet.CODE_UNFREEZE, "backup complete");
+          }
+        };
 
-                File choice = fc.getSelectedFile();
-    
-                logmsg("Chose backup dir: " + choice);
-                targetDir =
-                    new File(choice, "WF_" + System.currentTimeMillis());
-
-                ok = targetDir.mkdir();
-                if (!ok)
-                    ui.errorMessage("could not make Directory: " +
-                                    "\n\n      " + targetDir +
-                                    "\n\nPlease select another!" +
-                                    "");
-            }
+        /**
+         *  Do a recovery from a user-selected directory
+         *  that is hopefully the result of a previous backup.
+         */
+        Action recoveryaction = new AbstractAction("Recover Backup")
+        {
+          public void actionPerformed(ActionEvent evt)
+          {
+            sendAdminEvent(SOXWallet.CODE_SHUTDOWN, "recovery being attempted");
+            webfunds.client.utils.Backup.recover(ui, Core.userDir);
+            ui.infoMessage("Exiting now, you will need to restart " + me);
+            System.exit(0);
+          }
+        };
 
-            //
-            //  Now copy the entire "." into the directory.
-            //
-            try
-            {
-    
-                File srcDir = new File(".");
-    
-                webfunds.client.utils.FileUtils.copyTree(srcDir, targetDir);
+        /**
+         *  Yin - freeze the wallets.
+         */
+        Action yinaction = new AbstractAction("Yin")
+        {
+          public void actionPerformed(ActionEvent evt)
+          {
+            sendAdminEvent(SOXWallet.CODE_FREEZE, "Yin");
+          }
+        };
 
-                ui.infoMessage("Backup Complete");
-                return ;
-            }
-            catch (IOException ex)
-            {
-                ui.errorMessage("BACKUP FAILED!" +
-                                "\n\n      " + ex +
-                                "\n\nCheck " + targetDir + " for remains.");
-            }
+        /**
+         *  Yang - unfreeze the wallets.
+         */
+        Action yangaction = new AbstractAction("Yang")
+        {
+          public void actionPerformed(ActionEvent evt)
+          {
+            sendAdminEvent(SOXWallet.CODE_UNFREEZE, "Yang");
           }
         };
 
@@ -1022,6 +1022,9 @@
             menubar.add(helpmenu);
 
             filemenu.add(backupaction);
+            filemenu.add(recoveryaction);
+            filemenu.add(yinaction);
+            filemenu.add(yangaction);
             //toolbar.add(newaction);
             filemenu.add(new JSeparator());
             filemenu.add(exitaction);



1.65      +40 -67    java/webfunds/client/Core.java

Index: Core.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/client/Core.java,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -r1.64 -r1.65
--- Core.java	2000/09/18 17:02:26	1.64
+++ Core.java	2000/09/24 23:19:09	1.65
@@ -1,4 +1,4 @@
-/* $Id: Core.java,v 1.64 2000/09/18 17:02:26 iang Exp $
+/* $Id: Core.java,v 1.65 2000/09/24 23:19:09 iang Exp $
  *
  * Copyright (c) Systemics Inc. 1995-2000 on behalf of
  * The WebFunds Development Team.  All rights reserved.
@@ -24,10 +24,13 @@
 import webfunds.ricardian.ContractException;
 import webfunds.ricardian.ContractDirectoryException;
 import webfunds.ricardian.IniFileReader;
+
 import webfunds.client.contracts.ChangeContractStore;
 import webfunds.client.plugins.PluginException;
 import webfunds.client.plugins.PluginManager;
 import webfunds.client.plugins.WalletManager;
+import webfunds.client.utils.Startup;
+
 import webfunds.store.Store;
 import webfunds.store.StoreException;
 import webfunds.store.*;
@@ -36,6 +39,7 @@
 public final class Core
     extends Debug
 {
+                                           // grabbed by backups routine
     public static final File userDir     = new File("user");
     public static final File defaultDir  = new File("defaults");
     public static final File propfile    = new File(userDir, "props.dat");
@@ -49,7 +53,7 @@
     public static boolean testMode = false;
 
     /** take stuff from the defaults directory */
-    public static boolean defaults = false;
+    // public static boolean useDefaults = false;
 
     private final SecureRandom random;
 
@@ -64,7 +68,7 @@
 
     PrintWriter bug;
 
-    public Core()
+    public Core(boolean useDefaults)
     {
         /*
          * Obtains SecureRandom bypassing Sun's slow seeding process if 
@@ -116,7 +120,7 @@
         File consDir = new File(userDir, "contract");
         try {
             setContractStore( new ChangeContractStore(consDir, bug));
-            if (defaults)
+            if (useDefaults)
                 cs.addDirectory(new File(defaultDir, "contracts"));
         } catch (ContractDirectoryException ex) {
             logmsg("contracts directory is bad (exiting): " + ex);
@@ -187,8 +191,8 @@
         // Somewhere here, it freezes.
         //
         logmsg("CoreParts: ");
-        logmsg(" CP: multi ");
-        setStore(v2); // multistore);
+        logmsg(" CP: store ");
+        setStore(v2);
         logmsg(" CP: address ");
         setAddressbook(new Addressbook());
         logmsg(" CP: browser ");
@@ -204,6 +208,9 @@
 
         //
         // Adding plugins
+        //
+        // Need to move all this into the PluginManager (same as wallets).
+        //
         // Here, we need to add a PrintWriter in that
         // can be sent to the author of the Plugin.
         // Same for wallets probably.
@@ -226,21 +233,6 @@
             }
         }
 
-//        //
-//        // Adding 3rd party file plugins
-//        //
-//        logmsg("3rd Party Plugins: ==========================");
-//
-//        String[] plugs = VersionNumbers.getListOfAddOns(pluginsDir, bug);
-//
-//        for (int i = 0; i < plugs.length; i++)
-//        {
-//            try {
-//                pm.add3rdPartyPlugin(pluginsDir, plugs[i]);
-//            } catch (Exception ex) {
-//            }
-//        }
-
         logmsg("++++++++++++++++ plugged ++++++++++++++++");
         pm.plugged();
 
@@ -258,51 +250,10 @@
 
         logmsg("\n\n + + + + + + Run Now! + + + + + + \n");
         ab.run();
-
+        logmsg("\n\n - - - - - - Run Complete. - - - - - - \n");
     }
 
 
-//    static String sep = System.getProperty("path.separator");
-//
-//    protected void add3rdPartyPlugin(String dir, String name)
-//    {
-//        File pugDir  = new File(dir, name);
-//        File pugSpec = new File(pugDir, Plugin.spec);
-//
-//        // Read Plugin Spec
-//        byte[] buf;
-//        try {
-//            FileInputStream fis = new FileInputStream(pugSpec);
-//            buf = new byte[fis.available()];
-//            fis.read(buf);
-//            fis.close();
-//        } catch (IOException ex) {
-//            logmsg("Plugin " + pugDir + " failed.\n" +
-//                   "Ex: " + ex + "\n" +
-//                   "Spec " + spec + " not readable!  Contact your vendor!");
-//            return ;
-//        }
-//
-//        IniFileReader ini;
-//        try {
-//            ini = new IniFileReader(buf);
-//        } catch (ContractException ex) {
-//            logmsg("Plugin " + pugDir + " failed.\n" +
-//                   "Ex: " + ex + "\n" +
-//                   "IniFile " + spec + " not readable!  Contact your vendor!");
-//            return ;
-//        }
-//
-//        String main = ini.getSectionItemValue("java", "main");
-//        Properties props = System.getProperties();
-//        String classpath = System.getProperty("java.class.path");
-//        String sep = System.getProperty("line.separator");
-//        logmsg("classpath is " + classpath);
-//        classpath += sep + dir + sep + name;
-//        logmsg("new       is " + classpath);
-//        setProperty("java.class.path", classpath);
-//
-//    }
 
     private void setUInterface(UInterface uinterface)
     {
@@ -584,12 +535,34 @@
             }
         }
 
+        boolean useDefaults = false;
         if (!userDir.exists())
         {
-            System.err.println("New User!  use defaults");
-            defaults = true;
+            Startup startup = new Startup();
+            String s = startup.showDialog();
+            if (Startup.CANCEL.equals(s))
+                System.exit(0);
+
+            if (Startup.NEW_USER.equals(s))
+            {
+                System.err.println("New User!  use defaults");
+                userDir.mkdirs();
+                useDefaults = true;
+            }
+            else if (Startup.RECOVER.equals(s))
+            {
+                System.err.println("Recovered User!");
+                if (!userDir.exists())
+                {
+                    System.err.println("failed...");
+                    System.exit(0);
+                }
+            }
+            else
+            {
+                throw new InternalError("unknown Startup response: " + s);
+            }
         }
-        userDir.mkdirs();
 
         try {
             FileOutputStream fos = new FileOutputStream(Core.propfile);
@@ -599,7 +572,7 @@
             throw new RuntimeException(ex.getMessage());
         }
 
-        Core core = new Core();
+        Core core = new Core(useDefaults);
         System.err.println("done: " + core);
     }
 



1.38      +25 -1     java/webfunds/client/WalletInterface.java

Index: WalletInterface.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/client/WalletInterface.java,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- WalletInterface.java	2000/09/17 20:43:32	1.37
+++ WalletInterface.java	2000/09/24 23:19:09	1.38
@@ -1,5 +1,5 @@
 /*
- * $Id: WalletInterface.java,v 1.37 2000/09/17 20:43:32 iang Exp $
+ * $Id: WalletInterface.java,v 1.38 2000/09/24 23:19:09 iang Exp $
  *
  * Copyright (c) 1995-2000 Systemics Ltd on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
@@ -66,6 +66,28 @@
     void setWalletContext(WalletContext wm);
     
     /**
+     *  Signal the wallet.  For some reason, the application has
+     *  decided to conduct some admin, and wishes to freeze or
+     *  shut this wallet down;  the wallet should
+     *  cease doing anything that might involve state.
+     *
+     *  THIS IS NOT A SIGNAL TO SAVE DATA ;  ALL DATA SHOULD HAVE BEEN
+     *  SAVED ALREADY ACCORDING TO NORMAL TRANSACTIONAL PRINCIPLES!
+     *
+     *  Experimental call at this stage, the precise semantics are unclear.
+     *  May be irreversable..., see the codes in SOXWallet.
+     *  Purposes include backups and upgrades.
+     *
+     *  @param code a number that might indicate urgency or reason
+     *  @param reason a printable or loggable string that might indicate reason
+     *  @return 0 if wallet believes it has successfully shutdown,
+     *          else some number indicating something...
+     */
+    int adminEvent(int code, String reason);
+
+
+    
+    /**
      *  Get the value held in a subaccount (contract) in a given account. 
      *  If pending is true, what is returned is the sum of outstanding,
      *  non-confirmed transactions, i.e., those that haven't hit the
@@ -166,6 +188,8 @@
      */
     Transaction[] getTransactions(AccountInfo account, ItemId contract);
     
+
+
     /**
      *  Provide a help string for each of the different levels.
      */



1.134     +115 -3    java/webfunds/client/sox/SOXWallet.java

Index: SOXWallet.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/client/sox/SOXWallet.java,v
retrieving revision 1.133
retrieving revision 1.134
diff -u -r1.133 -r1.134
--- SOXWallet.java	2000/09/17 21:02:19	1.133
+++ SOXWallet.java	2000/09/24 23:19:10	1.134
@@ -1,4 +1,4 @@
-/* $Id: SOXWallet.java,v 1.133 2000/09/17 21:02:19 iang Exp $
+/* $Id: SOXWallet.java,v 1.134 2000/09/24 23:19:10 iang Exp $
  *
  * Copyright (c) Systemics Inc. 1995-2000 on behalf of
  * The WebFunds Development Team.  All Rights Reserved.
@@ -266,7 +266,50 @@
     }
 
 
+    /**
+     *  adminEvent() codes.
+     */
+    public static final int  CODE_SHUTDOWN = 0,  // stop, clean up everything
+                             CODE_FREEZE   = 1,  // to persistant files, backup
+                             CODE_UNFREEZE = 2;  // ok, carry on, backup done
+
+    private boolean   closed;
+    public boolean    isClosed()                     { return closed; }
+    private int       closeCode;
+    public int        closeCode()                    { return closeCode; }
+    private String    closeReason;
+    protected String  closeErrorReason;
+    public String     closeReason()                  { return closeReason; }
+
+    /**
+     *  Shutdown signal or similar.
+     *
+     *  Client Wallet Interface
+     */
+    public int adminEvent(int code, String reason)
+    {
+        if ((code == CODE_UNFREEZE) && (closeCode == CODE_SHUTDOWN))
+            return -1;
+
+        closeCode = code;
+        closeReason = reason;
+
+        if ((code == CODE_SHUTDOWN) || (code == CODE_FREEZE))
+        {
+            closed = true;
+            closeErrorReason = "Closed.\n\n    \"" + reason + "\"";
+        }
+        else
+        {
+            closed = false;
+            closeErrorReason = "(not closed)";
+        }
 
+        logmsg("ADMIN EVENT: (" + closeCode + ") " + closeReason);
+        return 0 ;
+    }
+
+
 /////////  Acquire Things  //////////////////////////////
 
     /**
@@ -523,6 +566,10 @@
                               long from, long till,
                               String pid)
     {
+        if (isClosed())
+            //throw new PaymentException(WalletException.CLOSED, closeReason());
+            return null;
+
         //  Need a quiet non-GUI version:  no AccountInfos, no error()'s  !
 
         if (amount < 0)
@@ -573,7 +620,7 @@
             String name = contractid.toString();
             if (contract != null)
             {
-                am = contract.getAmount(amount);
+                am = contract.getUnitsOfAccount(amount);
                 name = contract.getName();
             }
             String descString = Hex.printable(desc);
@@ -661,6 +708,9 @@
     {
         //  A First Cut at a quiet non-GUI version
 
+        if (isClosed())
+            throw new PaymentException(WalletException.CLOSED, closeReason());
+
         if (amount < 0)
             throw new IllegalArgumentException("amount " + amount + " < 0 !");
 
@@ -778,6 +828,12 @@
 
     public void makeDeposit(byte[] payment, AccountInfo callerAc, byte[] desc)
     {
+        if (isClosed())
+        {
+            error(closeErrorReason);
+            return ;
+        }
+
         byte[] buf = decodeSOXPayment(payment);
         if (buf == null)
         {
@@ -1064,6 +1120,9 @@
                              byte[] desc, String idempotentId)
         throws DepositException
     {
+        if (isClosed())
+            throw new DepositException(WalletException.CLOSED, closeReason());
+
         ENTER("doDeposit");
         TRACE("payment="  + payment  + 
             ", account=" + account+ 
@@ -1354,6 +1413,12 @@
      */
     public void cancel(Transaction trans)
     {
+        if (isClosed())
+        {
+            error(closeErrorReason);
+            return ;
+        }
+
         logmsg("cancelling Transaction " + trans);
 
 //        if (trans.getType() != Transaction.PAYMENT)
@@ -1402,7 +1467,6 @@
     public void cancel(AccountId account, ItemId item, String pid)
         throws CancelException, SOXLaterException
     {
-
         Account ac;
         try {
             ac = getAccount(account);
@@ -1468,6 +1532,8 @@
     protected void internalCancel(ValueAccount sub, String[] pids)
         throws CancelException, SOXLaterException
     {
+        if (isClosed())
+            throw new CancelException(WalletException.CLOSED, closeReason());
 
         AccountId acct = getAccountId(sub);
         ItemId item = sub.getItemId();
@@ -1567,7 +1633,10 @@
     protected void internalCancel(ValueAccount sub, String pid)
         throws CancelException, SOXLaterException
     {
+        if (isClosed())
+            throw new CancelException(WalletException.CLOSED, closeReason());
 
+
         AccountId acct = getAccountId(sub);
         ItemId item = sub.getItemId();
         logmsg("internalCancel(" + acct + "/" + item + ", " + pid + ")");
@@ -1620,6 +1689,11 @@
     protected MailItem[] quietCancel(ValueAccount sub, String pid)
         throws SOXLaterException, CancelException
     {
+        //
+        //  In theory, this doesn't change "state" as the important
+        //  event, the writing and saving of the payment, is done
+        //  elsewhere.
+        //
 
         logmsg("cancelling " + pid);
         MailItem[] mails;
@@ -1666,6 +1740,11 @@
      */
     public AccountInfo addAccount()
     {
+        if (isClosed())
+        {
+            error(closeErrorReason);
+            return null ;
+        }
 
         Account newacc = null;
         try
@@ -1729,6 +1808,11 @@
      */
     public boolean renameAccount(AccountInfo accountinfo, String name)
     {
+        if (isClosed())
+        {
+            error(closeErrorReason);
+            return false ;
+        }
 
         // AccountId acct = new AccountId();
         // acct.setId(accountinfo.getId());
@@ -1763,6 +1847,11 @@
      */
     public boolean removeAccount(AccountInfo accountinfo)
     {
+        if (isClosed())
+        {
+            error(closeErrorReason);
+            return false ;
+        }
 
         Account account;
         try
@@ -1810,6 +1899,12 @@
      */
     public boolean removeContract(AccountInfo accountinfo, ItemId item)
     {
+        if (isClosed())
+        {
+            error(closeErrorReason);
+            return false ;
+        }
+
         AccountId acct = new AccountId();
         acct.setId(accountinfo.getId());
 
@@ -1831,7 +1926,7 @@
         if (sub == null)
             return true ;  // or false?  either way, mission accomplished
 
-System.err.println("arrghh " + sub.getStatus());
+logmsg("arrghh " + sub.getStatus());
         //
         // This is a bit grotty.
         // The account is spread across the Account, SubAccounts,
@@ -1931,10 +2026,21 @@
 
 
     /**
+     *  Adds the contract to the Account.
+     *
      *  Client Wallet Interface
+     *
+     *  @return the itemId of the contract (even when already added),
+     *          or null on failure
      */
     public ItemId addContract(AccountInfo info, ItemId item)
     {
+        if (isClosed())
+        {
+            error(closeErrorReason);
+            return null ;
+        }
+
         Account acct = getAccountOrDie(info);
 
         //
@@ -2122,6 +2228,12 @@
      */
     protected void manyUpdates(SubAccount sub, MailItem[] mails)
     {
+        if (isClosed())
+        {
+            logmsg("closed, updated abandoned: " + closeReason);
+            return ;
+        }
+
         MailId[] confirms = null;
 
         logmsg("manyUpdates(" + ((mails == null)? 0: mails.length) + ")");



1.5       +4 -2      java/webfunds/client/sox/WalletException.java

Index: WalletException.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/client/sox/WalletException.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- WalletException.java	2000/09/17 19:42:24	1.4
+++ WalletException.java	2000/09/24 23:19:10	1.5
@@ -1,5 +1,5 @@
 /*
- * $Id: WalletException.java,v 1.4 2000/09/17 19:42:24 iang Exp $
+ * $Id: WalletException.java,v 1.5 2000/09/24 23:19:10 iang Exp $
  *
  * Copyright (c) 2000 Systemics Inc on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
@@ -36,8 +36,9 @@
 			    NOT_VALUE      = 107, // not a ValueAccount
                             NOT_ENUF_FUNDS = 108, // asking for too much!
                             PID_IN_USE     = 109, // requested pid already used
+                            CLOSED         = 110, // wallet has been shut down
 
-                            LAST_WALLET_ERRNO = 108;
+                            LAST_WALLET_ERRNO = 110;
 
     /**
      *  Use these rather than worry about which number...
@@ -67,6 +68,7 @@
                (number == Errors.ERROR_ALREADY);         // pid is used
     }
 
+    public boolean isClosed()   { return getNumber() == CLOSED ; }
 
 
     public WalletException(String msg)          { super(msg); number = 0; }