[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; }