Coverage Report - org.homeunix.thecave.buddi.Buddi
 
Classes in this File Line Coverage Branch Coverage Complexity
Buddi
41%
135/327
27%
43/159
5.097
Buddi$1
0%
0/3
N/A
5.097
Buddi$1$1
0%
0/15
0%
0/6
5.097
Buddi$2
83%
5/6
50%
1/2
5.097
Buddi$3
0%
0/22
0%
0/2
5.097
Buddi$3$1
0%
0/3
N/A
5.097
Buddi$4
100%
3/3
N/A
5.097
Buddi$5
0%
0/17
0%
0/2
5.097
Buddi$6
58%
36/62
50%
13/26
5.097
 
 1  
 /*
 2  
  * Created on Jun 26, 2005 by wyatt
 3  
  */
 4  
 package org.homeunix.thecave.buddi;
 5  
 
 6  
 import java.io.File;
 7  
 import java.io.FileInputStream;
 8  
 import java.io.FileNotFoundException;
 9  
 import java.io.FileOutputStream;
 10  
 import java.io.IOException;
 11  
 import java.io.InputStream;
 12  
 import java.io.OutputStream;
 13  
 import java.io.PrintStream;
 14  
 import java.net.InetAddress;
 15  
 import java.net.InetSocketAddress;
 16  
 import java.net.Proxy;
 17  
 import java.net.URL;
 18  
 import java.net.URLConnection;
 19  
 import java.util.Arrays;
 20  
 import java.util.Enumeration;
 21  
 import java.util.LinkedList;
 22  
 import java.util.List;
 23  
 import java.util.Properties;
 24  
 import java.util.Timer;
 25  
 import java.util.TimerTask;
 26  
 import java.util.logging.Handler;
 27  
 import java.util.logging.Level;
 28  
 import java.util.logging.Logger;
 29  
 import java.util.logging.SimpleFormatter;
 30  
 import java.util.logging.StreamHandler;
 31  
 
 32  
 import javax.swing.JOptionPane;
 33  
 import javax.swing.SwingUtilities;
 34  
 import javax.swing.UIManager;
 35  
 import javax.swing.plaf.FontUIResource;
 36  
 
 37  
 import net.java.dev.SwingWorker;
 38  
 
 39  
 import org.homeunix.thecave.buddi.i18n.BuddiKeys;
 40  
 import org.homeunix.thecave.buddi.i18n.keys.ButtonKeys;
 41  
 import org.homeunix.thecave.buddi.model.Document;
 42  
 import org.homeunix.thecave.buddi.model.impl.DocumentImpl;
 43  
 import org.homeunix.thecave.buddi.model.impl.ModelFactory;
 44  
 import org.homeunix.thecave.buddi.model.prefs.PrefsModel;
 45  
 import org.homeunix.thecave.buddi.plugin.BuddiPluginFactory;
 46  
 import org.homeunix.thecave.buddi.plugin.api.BuddiRunnablePlugin;
 47  
 import org.homeunix.thecave.buddi.plugin.api.exception.DataModelProblemException;
 48  
 import org.homeunix.thecave.buddi.plugin.api.exception.ModelException;
 49  
 import org.homeunix.thecave.buddi.plugin.api.util.TextFormatter;
 50  
 import org.homeunix.thecave.buddi.util.BuddiCryptoFactory;
 51  
 import org.homeunix.thecave.buddi.util.FileFunctions;
 52  
 import org.homeunix.thecave.buddi.util.OperationCancelledException;
 53  
 import org.homeunix.thecave.buddi.view.MainFrame;
 54  
 import org.homeunix.thecave.buddi.view.dialogs.BuddiPasswordDialog;
 55  
 import org.homeunix.thecave.buddi.view.menu.bars.FramelessMenuBar;
 56  
 import org.homeunix.thecave.buddi.view.menu.items.EditPreferences;
 57  
 import org.homeunix.thecave.buddi.view.menu.items.FileOpen;
 58  
 import org.homeunix.thecave.buddi.view.menu.items.FileQuit;
 59  
 import org.homeunix.thecave.buddi.view.menu.items.HelpAbout;
 60  
 
 61  
 import ca.digitalcave.moss.application.document.exception.DocumentLoadException;
 62  
 import ca.digitalcave.moss.application.document.exception.DocumentSaveException;
 63  
 import ca.digitalcave.moss.common.LogUtil;
 64  
 import ca.digitalcave.moss.common.OperatingSystemUtil;
 65  
 import ca.digitalcave.moss.common.ParseCommands;
 66  
 import ca.digitalcave.moss.common.StreamUtil;
 67  
 import ca.digitalcave.moss.common.Version;
 68  
 import ca.digitalcave.moss.common.ParseCommands.ParseResults;
 69  
 import ca.digitalcave.moss.common.ParseCommands.ParseVariable;
 70  
 import ca.digitalcave.moss.crypto.IncorrectPasswordException;
 71  
 import ca.digitalcave.moss.osx.Application;
 72  
 import ca.digitalcave.moss.osx.ApplicationAdapter;
 73  
 import ca.digitalcave.moss.osx.ApplicationEvent;
 74  
 import ca.digitalcave.moss.swing.ApplicationModel;
 75  
 import ca.digitalcave.moss.swing.LookAndFeelUtil;
 76  
 import ca.digitalcave.moss.swing.MossFrame;
 77  
 import ca.digitalcave.moss.swing.exception.WindowOpenException;
 78  
 import edu.stanford.ejalbert.BrowserLauncher;
 79  
 
 80  
 /**
 81  
  * The main class, containing the launch methods for Buddi.  This class 
 82  
  * is responsible for setting up the environment (including reading
 83  
  * command line options), loading the preferences and languages, 
 84  
  * warning the user (if using experimental code), etc.  It also initializes
 85  
  * and contains access methods for several environment-type methods,
 86  
  * such as what OS we are running on, and what the working directory is.
 87  
  * 
 88  
  * @author wyatt
 89  
  * @author jdidion - Split the LNF dialog into its own class for better maintainability
 90  
  */
 91  2986
 public class Buddi {
 92  
 
 93  
 //        private static String userDir;
 94  
         private static String pluginsFolder;
 95  
         private static String languagesFolder;
 96  
         private static String reportsFolder;
 97  
         private static List<File> filesToLoad;
 98  2986
         private static Boolean noAutoSave = false;
 99  2986
         private static Boolean debian = false;
 100  2986
         private static Boolean windowsInstaller = false;
 101  2986
         private static Boolean genericUnix = false;
 102  2986
         private static Boolean slackware = false;
 103  2986
         private static Boolean redhat = false;
 104  2986
         private static File logFile = null;
 105  2986
         private static Version version = null;
 106  
 
 107  
         public static Version getVersion() {
 108  6405
                 if (version == null)
 109  2986
                         version = Version.getVersionResource("version.txt");
 110  6405
                 return version;
 111  
         }
 112  
 
 113  
         /** 
 114  
          * @return True if running on generic Unix, false otherwise.  This is 
 115  
          * obtained through the startup flag --unix, so it can be 
 116  
          * faked if desired.  This is used to determine which download
 117  
          * to use on Linux - if the flag is set, we will download
 118  
          * a .deb when a new version is released, otherwise we will
 119  
          * download a .jar.
 120  
          */
 121  
         public static boolean isUnix(){
 122  3
                 if (genericUnix == null)
 123  0
                         genericUnix = false;
 124  3
                 return genericUnix;
 125  
         }
 126  
 
 127  
         /** 
 128  
          * @return True if running on Slackware, false otherwise.  This is 
 129  
          * obtained through the startup flag --slackware, so it can be 
 130  
          * faked if desired.  This is used to determine which download
 131  
          * to use on Linux - if the flag is set, we will download
 132  
          * a .deb when a new version is released, otherwise we will
 133  
          * download a .jar.
 134  
          */
 135  
         public static boolean isSlackware(){
 136  3
                 if (slackware == null)
 137  0
                         slackware = false;
 138  3
                 return slackware;
 139  
         }
 140  
 
 141  
         /**
 142  
          * @return True if running from a Windows Installer installed .exe, false
 143  
          * otherwise.  This is obtained through the startup flag --windows-installer, so it can be 
 144  
          * faked if desired.  This is used to determine which download
 145  
          * to use on Windows - if the flag is set, we will download
 146  
          * the installer version when a new version is released, otherwise we will
 147  
          * download the standalone .exe.
 148  
          */
 149  
         public static boolean isWindowsInstaller(){
 150  0
                 if (windowsInstaller == null)
 151  0
                         windowsInstaller = false;
 152  0
                 return windowsInstaller;
 153  
         }
 154  
 
 155  
 
 156  
         /** 
 157  
          * @return True if running on Redhat, false otherwise.  This is 
 158  
          * obtained through the startup flag --debian, so it can be 
 159  
          * faked if desired.  This is used to determine which download
 160  
          * to use on Linux - if the flag is set, we will download
 161  
          * a .deb when a new version is released, otherwise we will
 162  
          * download a .jar.
 163  
          */
 164  
         public static boolean isRedhat(){
 165  3
                 if (redhat == null)
 166  0
                         redhat = false;
 167  3
                 return redhat;
 168  
         }
 169  
 
 170  
         /** 
 171  
          * @return True if running on Debian, false otherwise.  This is 
 172  
          * obtained through the startup flag --debian, so it can be 
 173  
          * faked if desired.  This is used to determine which download
 174  
          * to use on Linux - if the flag is set, we will download
 175  
          * a .deb when a new version is released, otherwise we will
 176  
          * download a .jar.
 177  
          */
 178  
         public static boolean isDebian(){
 179  3
                 if (debian == null)
 180  0
                         debian = false;
 181  3
                 return debian;
 182  
         }
 183  
 
 184  
         private static boolean isAutoSave(){
 185  2977
                 if (noAutoSave == null)
 186  0
                         noAutoSave = false;
 187  2977
                 return !noAutoSave;
 188  
         }
 189  
 
 190  
         public static File getPluginsFolder(){
 191  23199
                 if (pluginsFolder == null)
 192  2986
                         pluginsFolder = OperatingSystemUtil.getUserFolder("Buddi") + File.separator + Const.PLUGIN_FOLDER;
 193  23199
                 return new File(pluginsFolder);
 194  
         }
 195  
 
 196  
         public static File getReportsFolder(){
 197  0
                 if (reportsFolder == null)
 198  0
                         reportsFolder = OperatingSystemUtil.getUserFolder("Buddi") + File.separator + Const.REPORT_FOLDER;
 199  0
                 return new File(reportsFolder);
 200  
         }        
 201  
 
 202  
         public static File getLanguagesFolder(){
 203  3724
                 if (languagesFolder == null)
 204  2986
                         languagesFolder = OperatingSystemUtil.getUserFile("Buddi", Const.LANGUAGE_FOLDER).getAbsolutePath();
 205  3724
                 Logger.getLogger(Buddi.class.getName()).finest(languagesFolder);
 206  3724
                 return new File(languagesFolder);
 207  
         }
 208  
 
 209  
         /**
 210  
          * Method to start the GUI.  Should be run from the AWT Dispatch thread.
 211  
          */
 212  
         private static void launchGUI(){
 213  
                 //If we are on a Mac, open a new Frameless menu bar.
 214  2986
                 if (OperatingSystemUtil.isMac()){
 215  0
                         Application.getApplication().setFramessMenuBar(new FramelessMenuBar());
 216  
                 }
 217  
 
 218  
                 //Handle opening files from command line.
 219  2986
                 if (filesToLoad.size() > 0){
 220  0
                         for (File f : filesToLoad) {
 221  0
                                 openFile(f);
 222  
                         }
 223  
                 }
 224  
 
 225  
                 //If we have found a new version last time, we prompt for it now.
 226  2986
                 if (PrefsModel.getInstance().isShowUpdateNotifications() 
 227  
                                 && PrefsModel.getInstance().getAvailableVersion() != null){
 228  0
                         Version availableVersion = new Version(PrefsModel.getInstance().getAvailableVersion());
 229  0
                         Version thisVersion = getVersion();
 230  
 
 231  0
                         if (thisVersion.compareTo(availableVersion) < 0){
 232  0
                                 String[] buttons = new String[2];
 233  0
                                 buttons[0] = TextFormatter.getTranslation(ButtonKeys.BUTTON_DOWNLOAD);
 234  0
                                 buttons[1] = TextFormatter.getTranslation(ButtonKeys.BUTTON_CANCEL);
 235  
 
 236  0
                                 int reply = JOptionPane.showOptionDialog(
 237  
                                                 null,
 238  
                                                 TextFormatter.getTranslation(BuddiKeys.NEW_VERSION_MESSAGE)
 239  
                                                 + " " + PrefsModel.getInstance().getAvailableVersion() + "\n"
 240  
                                                 + TextFormatter.getTranslation(BuddiKeys.NEW_VERSION_MESSAGE_2),
 241  
                                                 TextFormatter.getTranslation(BuddiKeys.NEW_VERSION),
 242  
                                                 JOptionPane.YES_NO_OPTION,
 243  
                                                 JOptionPane.INFORMATION_MESSAGE,
 244  
                                                 null,
 245  
                                                 buttons,
 246  
                                                 buttons[0]);
 247  
 
 248  0
                                 if (reply == JOptionPane.YES_OPTION){
 249  
                                         String fileLocation;
 250  0
                                         if (Const.BRANCH.equals(Const.STABLE))
 251  0
                                                 fileLocation = Const.DOWNLOAD_URL_STABLE;
 252  
                                         else
 253  0
                                                 fileLocation = Const.DOWNLOAD_URL_UNSTABLE;
 254  
 
 255  
                                         //Link to the correct download by default.
 256  0
                                         if (OperatingSystemUtil.isMac())
 257  0
                                                 fileLocation += Const.DOWNLOAD_TYPE_OSX;
 258  0
                                         else if (OperatingSystemUtil.isWindows()){
 259  0
                                                 if (isWindowsInstaller())
 260  0
                                                         fileLocation += Const.DOWNLOAD_TYPE_WINDOWS_INSTALLER;
 261  
                                                 else
 262  0
                                                         fileLocation += Const.DOWNLOAD_TYPE_WINDOWS;
 263  
                                         }
 264  
                                         else {
 265  
                                                 //Check for any specific distributions here
 266  0
                                                 if (Buddi.isDebian())
 267  0
                                                         fileLocation += Const.DOWNLOAD_TYPE_DEBIAN;
 268  0
                                                 else if (Buddi.isSlackware())
 269  0
                                                         fileLocation += Const.DOWNLOAD_TYPE_SLACKWARE;
 270  0
                                                 else if (Buddi.isRedhat())
 271  0
                                                         fileLocation += Const.DOWNLOAD_TYPE_REDHAT;
 272  0
                                                 else if (Buddi.isUnix())
 273  0
                                                         fileLocation += Const.DOWNLOAD_TYPE_UNIX;
 274  
                                                 else
 275  0
                                                         fileLocation += Const.DOWNLOAD_TYPE_GENERIC;
 276  
                                         }
 277  
 
 278  
                                         try{
 279  0
                                                 BrowserLauncher bl = new BrowserLauncher(null);
 280  0
                                                 bl.openURLinBrowser(fileLocation);
 281  
                                         }
 282  0
                                         catch (Exception e){
 283  0
                                                 Logger.getLogger(Buddi.class.getName()).log(Level.WARNING, "Unknown Exception", e);
 284  0
                                         }
 285  
                                 }
 286  
                         }
 287  
                 }
 288  
 
 289  
                 //If we have specified that we want to prompt for a data file at startup,
 290  
                 // do so (assuming that we have not already opened one from the command
 291  
                 // line, or Mac Application listeners.
 292  2986
                 if (PrefsModel.getInstance().isShowPromptAtStartup()
 293  
                                 && ApplicationModel.getInstance().getOpenFrames().size() == 0){
 294  0
                         new FileOpen(null).doClick();
 295  
                 }
 296  
 
 297  
                 //Handle opening the last user file, if available.
 298  2986
                 if (PrefsModel.getInstance().getLastDataFiles() != null
 299  
                                 && ApplicationModel.getInstance().getOpenFrames().size() == 0) {
 300  0
                         for (File f : PrefsModel.getInstance().getLastDataFiles()) {
 301  0
                                 openFile(f);                                
 302  
                         }
 303  
                 }
 304  
 
 305  
                 //If no files are available, just create a new one.
 306  2986
                 if (ApplicationModel.getInstance().getOpenFrames().size() == 0) {
 307  
                         try {
 308  2986
                                 Document model = ModelFactory.createDocument();
 309  2986
                                 MainFrame mainWndow = new MainFrame(model);
 310  
                                 try{
 311  2977
                                         mainWndow.openWindow(
 312  
                                                         PrefsModel.getInstance().getWindowSize(model.getFile() + ""), 
 313  
                                                         PrefsModel.getInstance().getWindowLocation(model.getFile() + ""));
 314  
                                 }
 315  2977
                                 catch (WindowOpenException woe){}
 316  
                         }
 317  0
                         catch (ModelException me){
 318  0
                                 Logger.getLogger(Buddi.class.getName()).log(Level.SEVERE, "Model Exception", me);
 319  2977
                         }
 320  
                 }
 321  
 
 322  
                 //Check if we have opened at least one window...
 323  2977
                 MainFrame mainFrame = null;
 324  2977
                 for (MossFrame mossFrame : ApplicationModel.getInstance().getOpenFrames()) {
 325  2977
                         if (mossFrame instanceof MainFrame){
 326  2977
                                 mainFrame = (MainFrame) mossFrame;
 327  2977
                                 break;
 328  
                         }
 329  
                 }
 330  2977
                 if (mainFrame == null)
 331  0
                         Logger.getLogger(Buddi.class.getName()).severe("No Buddi main windows were able to open!");
 332  
 
 333  
                 //Start the background startup tasks... 
 334  2977
                 startVersionCheck(mainFrame);
 335  2977
                 startUpdateCheck(mainFrame);
 336  
 
 337  
 
 338  
                 //Start the auto save timer
 339  2977
                 if (isAutoSave()){
 340  0
                         Timer t = new Timer();
 341  0
                         t.schedule(new TimerTask(){
 342  
                                 @Override
 343  
                                 public void run() {
 344  0
                                         SwingUtilities.invokeLater(new Runnable(){
 345  
                                                 public void run() {        
 346  0
                                                         for (MossFrame frame : ApplicationModel.getInstance().getOpenFrames()) {
 347  0
                                                                 if (frame instanceof MainFrame){
 348  0
                                                                         MainFrame mainFrame = (MainFrame) frame;
 349  0
                                                                         if (mainFrame.getDocument().isChanged()){
 350  0
                                                                                 File autoSaveLocation = ModelFactory.getAutoSaveLocation(mainFrame.getDocument().getFile());
 351  
 
 352  
                                                                                 try {
 353  0
                                                                                         ((DocumentImpl) mainFrame.getDocument()).saveAuto(autoSaveLocation);
 354  0
                                                                                         Logger.getLogger(this.getClass().getName()).finest("Auto saved file to " + autoSaveLocation);
 355  
                                                                                 }
 356  0
                                                                                 catch (DocumentSaveException dse){
 357  0
                                                                                         Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Error saving autosave file", dse);
 358  0
                                                                                 }
 359  0
                                                                         }
 360  
                                                                         else {
 361  0
                                                                                 Logger.getLogger(this.getClass().getName()).finest("Did not autosave, as there are no changes to the data file " + mainFrame.getDocument().getFile());
 362  
                                                                         }                
 363  0
                                                                 }
 364  
                                                         }
 365  0
                                                 };
 366  
                                         });
 367  0
                                 }
 368  
                         }, 
 369  
                         PrefsModel.getInstance().getAutosaveDelay() * 1000, 
 370  
                         PrefsModel.getInstance().getAutosaveDelay() * 1000); //Use preferences to decide save period
 371  
                 }
 372  
 
 373  
                 //If it has not already been done, disable the splash screen now.
 374  
 //                MossSplashScreen.hideSplash();
 375  2977
         }
 376  
 
 377  
 
 378  
         /**
 379  
          * Opens the given file.  Must be run in the event dispatch thread. 
 380  
          * @param f
 381  
          */
 382  
         private static void openFile(File f){
 383  
                 //Handle opening files from command line.
 384  0
                 if (f.getName().endsWith(Const.DATA_FILE_EXTENSION)){
 385  
                         try {
 386  
 //                                MossSplashScreen.hideSplash();
 387  
 
 388  
                                 Document model;
 389  0
                                 model = ModelFactory.createDocument(f);
 390  
 
 391  0
                                 MainFrame mainWndow = new MainFrame(model);
 392  
                                 try {
 393  0
                                         mainWndow.openWindow(
 394  
                                                         PrefsModel.getInstance().getWindowSize(model.getFile() + ""), 
 395  
                                                         PrefsModel.getInstance().getWindowLocation(model.getFile() + ""));
 396  
                                 }
 397  0
                                 catch (WindowOpenException woe){}
 398  
                         }
 399  0
                         catch (DocumentLoadException lme){
 400  0
                                 Logger.getLogger(Buddi.class.getName()).log(Level.WARNING, "Error loading document", lme);
 401  
                         }
 402  0
                         catch (OperationCancelledException oce){}  //Do nothing
 403  
                 }
 404  0
                 else if (f.getName().endsWith(Const.PLUGIN_EXTENSION)){
 405  0
                         Logger.getLogger(Buddi.class.getName()).info("Trying to copy " + f.getAbsolutePath() + " to " + Buddi.getPluginsFolder() + File.separator + f.getName());
 406  0
                         if (!Buddi.getPluginsFolder().exists()){
 407  0
                                 if (!Buddi.getPluginsFolder().mkdirs()){
 408  0
                                         Logger.getLogger(Buddi.class.getName()).warning("Error creating Plugins directory!");
 409  
                                 }
 410  
                         }
 411  
                         try {
 412  0
                                 File dest = new File(Buddi.getPluginsFolder().getAbsolutePath() + File.separator + f.getName());
 413  0
                                 if (f.getAbsolutePath().equals(dest.getAbsolutePath()))
 414  0
                                         throw new IOException("Cannot copy to the same file.");
 415  0
                                 FileFunctions.copyFile(f, dest);
 416  
 
 417  0
                                 String[] options = new String[1];
 418  0
                                 options[0] = TextFormatter.getTranslation(ButtonKeys.BUTTON_OK);
 419  
 
 420  0
                                 JOptionPane.showOptionDialog(
 421  
                                                 null, 
 422  
                                                 TextFormatter.getTranslation(BuddiKeys.MESSAGE_PLUGIN_ADDED_RESTART_NEEDED),
 423  
                                                 TextFormatter.getTranslation(BuddiKeys.MESSAGE_PLUGIN_ADDED_RESTART_NEEDED_TITLE),
 424  
                                                 JOptionPane.OK_CANCEL_OPTION,
 425  
                                                 JOptionPane.INFORMATION_MESSAGE,
 426  
                                                 null,
 427  
                                                 options,
 428  
                                                 options[0]
 429  
                                 );
 430  
                         }
 431  0
                         catch (IOException ioe){
 432  0
                                 Logger.getLogger(Buddi.class.getName()).log(Level.WARNING, "Error copying plugin to Plugins directory", ioe);
 433  0
                         }
 434  
                 }
 435  0
                 else if (f.getName().endsWith(Const.LANGUAGE_EXTENSION)){
 436  0
                         Logger.getLogger(Buddi.class.getName()).info("Trying to copy " + f.getAbsolutePath() + " to " + Buddi.getLanguagesFolder() + File.separator + f.getName());
 437  0
                         if (!Buddi.getLanguagesFolder().exists()){
 438  0
                                 if (!Buddi.getLanguagesFolder().mkdirs()){
 439  0
                                         Logger.getLogger(Buddi.class.getName()).warning("Error creating Languages directory!");
 440  
                                 }
 441  
                         }
 442  
                         try {
 443  0
                                 File dest = new File(Buddi.getLanguagesFolder().getAbsolutePath() + File.separator + f.getName());
 444  0
                                 if (f.getAbsolutePath().equals(dest.getAbsolutePath()))
 445  0
                                         throw new IOException("Cannot copy to the same file.");
 446  0
                                 FileFunctions.copyFile(f, dest);
 447  
 
 448  0
                                 String[] options = new String[1];
 449  0
                                 options[0] = TextFormatter.getTranslation(ButtonKeys.BUTTON_OK);
 450  
 
 451  0
                                 JOptionPane.showOptionDialog(
 452  
                                                 null, 
 453  
                                                 TextFormatter.getTranslation(BuddiKeys.MESSAGE_LANGUAGE_ADDED_RESTART_NEEDED),
 454  
                                                 TextFormatter.getTranslation(BuddiKeys.MESSAGE_LANGUAGE_ADDED_RESTART_NEEDED_TITLE),
 455  
                                                 JOptionPane.OK_CANCEL_OPTION,
 456  
                                                 JOptionPane.INFORMATION_MESSAGE,
 457  
                                                 null,
 458  
                                                 options,
 459  
                                                 options[0]
 460  
                                 );
 461  
 
 462  0
                                 PrefsModel.getInstance().setLanguage(f.getName().replaceAll(Const.LANGUAGE_EXTENSION, ""));
 463  0
                                 PrefsModel.getInstance().save();
 464  
                         }
 465  0
                         catch (IOException ioe){
 466  0
                                 Logger.getLogger(Buddi.class.getName()).log(Level.WARNING, "Error copying translation to Languages directory", ioe);
 467  0
                         }
 468  
                 }
 469  0
         }
 470  
 
 471  
 
 472  
         /**
 473  
          * Main method for Buddi.  Can pass certain command line options
 474  
          * in.  Use --help flag to see complete list.
 475  
          * @param args
 476  
          */
 477  
         @SuppressWarnings("unchecked")
 478  
         public static void main(String[] args) {
 479  
                 //Set Buddi-specific LnF options, mostly (all?) for Quaqua.
 480  
                 //This one removes the width limitation for dialogs.  Since we already will
 481  
                 // wrap for other OS's, there is no need to have Quaqua do this for you.
 482  2986
                 UIManager.put("OptionPane.maxCharactersPerLineCount", Integer.MAX_VALUE);
 483  
                 //Set the max row count.  Quaqua overrides the value set in MossScrollingComboBox, 
 484  
                 // so we must set it here manually. 
 485  2986
                 UIManager.put("ComboBox.maximumRowCount", Integer.valueOf(10));
 486  
 
 487  2986
                 System.setProperty("com.apple.mrj.application.apple.menu.about.name", Const.PROJECT_NAME);
 488  
 
 489  2986
                 String help = "USAGE: java -jar Buddi.jar <options> <data file>, where options include:\n"
 490  
                         + "--usb\t\tRun on a USB key: put preferences, languages, and plugins in working dir.\n"
 491  
                         + "--prefs\tFilename\tPath and name of Preference File (Default varies by platform)\n"
 492  
                         + "--verbosity\t0-5\tVerbosity Level (0 = Emergency, 7 = Verbose)\n"
 493  
                         + "--languages\tFolder\tFolder to store custom languages (should be writable; default varies by platform)\n"
 494  
                         + "--plugins\tFolder\tFolder to store plugins (should be writable; default varies by platform)\n"
 495  
                         + "--nosplash\t\tDon't show splash screen on startup\n"
 496  
                         + "--lnf\tclassname\tTry to use the given LnF; you must manually include the LnF jar in the classpath\n"
 497  
                         + "--extract\tData File\tExtracts the XML contents of the given file, to Filename.xml.  Used for debugging.\n"
 498  
                         + "--log\tlogFile\tLocation to store logs, or 'stdout' / 'stderr' (default varies by platform)\n";
 499  
                 // Undocumented flag --font        <fontName> will specify a font to use by default
 500  
                 // Undocumented flag --windows-installer will specify a -Installer.exe download for new versions.
 501  
                 // Undocumented flag --debian will specify a .deb download for new versions.
 502  
                 // Undocumented flag --redhat will specify a .rpm download for new versions.
 503  
                 // Undocumented flag --slackware will specify a -Slackware.tgz download for new versions.
 504  
                 // Undocumented flag --unix will specify a .tgz download for new versions.
 505  
                 // Undocumented flag --noautosave will disable auto save (for development testing).
 506  
 
 507  2986
                 List<ParseVariable> variables = new LinkedList<ParseVariable>();
 508  2986
                 variables.add(new ParseVariable("--usb", Boolean.class, false));
 509  2986
                 variables.add(new ParseVariable("--prefs", String.class, false));
 510  2986
                 variables.add(new ParseVariable("--verbosity", Integer.class, false));
 511  2986
                 variables.add(new ParseVariable("--plugins", String.class, false));
 512  2986
                 variables.add(new ParseVariable("--languages", String.class, false));
 513  2986
                 variables.add(new ParseVariable("--log", String.class, false));
 514  2986
                 variables.add(new ParseVariable("--nosplash", Boolean.class, false));
 515  2986
                 variables.add(new ParseVariable("--noautosave", Boolean.class, false));
 516  2986
                 variables.add(new ParseVariable("--extract", String.class, false));
 517  2986
                 variables.add(new ParseVariable("--reports", String.class, false));
 518  2986
                 variables.add(new ParseVariable("--lnf", String.class, false));
 519  
 
 520  2986
                 variables.add(new ParseVariable("--font", String.class, false));
 521  
 
 522  2986
                 variables.add(new ParseVariable("--debian", Boolean.class, false));
 523  2986
                 variables.add(new ParseVariable("--redhat", Boolean.class, false));
 524  2986
                 variables.add(new ParseVariable("--slackware", Boolean.class, false));
 525  2986
                 variables.add(new ParseVariable("--unix", Boolean.class, false));
 526  2986
                 variables.add(new ParseVariable("--windows-installer", Boolean.class, false));
 527  
 
 528  2986
                 ParseResults results = ParseCommands.parse(args, help, variables);
 529  
 
 530  
                 //Extract file to stdout, and exit.
 531  2986
                 if (results.getString("--extract") != null){
 532  0
                         extractFile(new File(results.getString("--extract")));
 533  0
                         System.exit(0);
 534  
                 }
 535  
                 
 536  
                 //Load the correct Look and Feel.  Includes OS specific options, such as Quaqua constants.
 537  2986
                 LookAndFeelUtil.setLookAndFeel(results.getString("--lnf"));
 538  
 
 539  2986
                 splash: if (!OperatingSystemUtil.isMac()){
 540  2986
                         for (String string : args) {
 541  2986
                                 if (string.equals("--nosplash"))
 542  2986
                                         break splash;
 543  
                         }
 544  
 //                        MossSplashScreen.showSplash("img/BuddiSplashScreen.jpg");
 545  
                 }
 546  
 
 547  
                 //Catch runtime exceptions
 548  2986
                 Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
 549  
                         public void uncaughtException(Thread arg0, Throwable arg1) {
 550  87
                                 Logger.getLogger(Buddi.class.getName()).log(Level.SEVERE, "Uncaught exception", arg1);
 551  87
                                 if (arg1 instanceof DataModelProblemException)
 552  0
                                         sendBugReport(((DataModelProblemException) arg1).getDataModel());
 553  
                                 else
 554  87
                                         sendBugReport();
 555  87
                         }
 556  
                 });
 557  
 
 558  
                 //Early on, we need to catch any open requests from Apple Launchd.
 559  2986
                 if (OperatingSystemUtil.isMac()){
 560  0
                         Application application = Application.getApplication();
 561  0
                         application.addAboutMenuItem();
 562  0
                         application.addPreferencesMenuItem();
 563  0
                         application.setEnabledAboutMenu(true);
 564  0
                         application.setEnabledPreferencesMenu(true);
 565  0
                         application.addApplicationListener(new ApplicationAdapter(){
 566  
                                 @Override
 567  
                                 public void handleAbout(ApplicationEvent arg0) {
 568  0
                                         new HelpAbout(null).doClick();
 569  0
                                         arg0.setHandled(true);
 570  0
                                 }
 571  
 
 572  
                                 @Override
 573  
                                 public void handleOpenFile(final ApplicationEvent arg0) {
 574  0
                                         arg0.setHandled(true);
 575  0
                                         SwingUtilities.invokeLater(new Runnable(){
 576  
                                                 public void run() {
 577  0
                                                         openFile(new File(arg0.getFilename()));
 578  0
                                                 }
 579  
                                         });
 580  0
                                 }
 581  
 
 582  
                                 @Override
 583  
                                 public void handleReOpenApplication(ApplicationEvent arg0) {
 584  0
                                         arg0.setHandled(true);
 585  
 
 586  0
                                         if (ApplicationModel.getInstance().getOpenFrames().size() == 0){
 587  
                                                 try {
 588  0
                                                         Document model = ModelFactory.createDocument();
 589  0
                                                         MainFrame mainWndow = new MainFrame(model);
 590  0
                                                         mainWndow.openWindow(
 591  
                                                                         PrefsModel.getInstance().getWindowSize(model.getFile() + ""), 
 592  
                                                                         PrefsModel.getInstance().getWindowLocation(model.getFile() + ""));
 593  
                                                 }
 594  0
                                                 catch (ModelException me){
 595  0
                                                         Logger.getLogger(Buddi.class.getName()).log(Level.WARNING, "Model Exception", me);
 596  
                                                 }
 597  0
                                                 catch (WindowOpenException woe){}
 598  
                                         }
 599  0
                                 }
 600  
 
 601  
                                 @Override
 602  
                                 public void handlePreferences(ApplicationEvent arg0) {
 603  0
                                         new EditPreferences(null).doClick();
 604  0
                                         arg0.setHandled(true);
 605  0
                                 }
 606  
 
 607  
                                 @Override
 608  
                                 public void handleQuit(ApplicationEvent arg0) {
 609  0
                                         arg0.setHandled(false);  //You must set this to false if you want to be able to cancel it.
 610  0
                                         new FileQuit(null).doClick();
 611  0
                                 }
 612  
                         });
 613  
                 }
 614  
 
 615  
                 //Set up the logging system.  If we have specified --log, we first
 616  
                 // try using that file.  If that is not specified, we use the OS
 617  
                 // specific log file location.
 618  
                 try {
 619  2986
                         PrintStream logStream = System.err; //Default to stderr
 620  2986
                         if (results.getString("--log") != null){
 621  0
                                 if (results.getString("--log").equals("stdout"))
 622  0
                                         logStream = System.out;
 623  0
                                 else if (results.getString("--log").equals("stderr"))
 624  0
                                         logStream = System.err;
 625  
                                 else {
 626  0
                                         logFile = new File(results.getString("--log"));
 627  
                                 }
 628  
                         }
 629  
                         else
 630  2986
                                 logFile = OperatingSystemUtil.getLogFile("Buddi", Const.LOG_FILE);
 631  
 
 632  2986
                         if (logFile != null){
 633  2986
                                 if (!logFile.getParentFile().exists())
 634  0
                                         logFile.getParentFile().mkdirs();
 635  2986
                                 if (logFile.getParentFile().exists())
 636  2986
                                         logStream = new PrintStream(logFile);
 637  
                         }
 638  
                         
 639  2986
                         Logger logger = Logger.getLogger("org.homeunix.thecave");
 640  2986
                         Handler streamHandler = new StreamHandler(logStream, new SimpleFormatter());
 641  2986
                         logger.addHandler(streamHandler);
 642  
                 }
 643  0
                 catch (FileNotFoundException fnfe){
 644  0
                         Logger.getLogger(Buddi.class.getName()).log(Level.WARNING, "Cannot open log file", fnfe);
 645  2986
                 }
 646  
 
 647  
                 //Set up the log levels
 648  2986
                 Integer verbosity = results.getInteger("--verbosity");
 649  2986
                 if (verbosity != null){
 650  
                         Level level;
 651  0
                         switch (verbosity) {
 652  
                         case 0:
 653  0
                                 level = Level.SEVERE;
 654  0
                                 break;
 655  
                         case 1:
 656  0
                                 level = Level.WARNING;
 657  0
                                 break;
 658  
                         case 2:
 659  0
                                 level = Level.WARNING;
 660  0
                                 break;
 661  
                         case 3:
 662  0
                                 level = Level.INFO;
 663  0
                                 break;
 664  
                         case 4:
 665  0
                                 level = Level.INFO;
 666  0
                                 break;
 667  
                         case 5:
 668  0
                                 level = Level.FINE;
 669  0
                                 break;
 670  
                         case 6:
 671  0
                                 level = Level.FINER;
 672  0
                                 break;
 673  
                         case 7:
 674  0
                                 level = Level.FINEST;
 675  0
                                 break;
 676  
                         default:
 677  0
                                 level = Level.INFO;
 678  
                                 break;
 679  
                         }
 680  
 
 681  0
                         LogUtil.setLogLevel(level.toString());
 682  0
                         Logger.getLogger(Buddi.class.getName()).finest("Setting log level to " + level);
 683  0
                 }
 684  
                 else {
 685  2986
                         if (Const.DEVEL)
 686  0
                                 Logger.getLogger("org.homeunix.thecave").setLevel(Level.FINEST);
 687  
                         else
 688  2986
                                 Logger.getLogger(Buddi.class.getName()).setLevel(Level.INFO);
 689  
                 }
 690  
 
 691  
                 //Prints the version of Buddi to the logs
 692  2986
                 Logger.getLogger(Buddi.class.getName()).info("Buddi version: " + getVersion());
 693  2986
                 Logger.getLogger(Buddi.class.getName()).info("Buddi command line arguments: " + Arrays.toString(args));
 694  2986
                 Logger.getLogger(Buddi.class.getName()).info("Operating System: " + System.getProperty("os.name") + ", " + System.getProperty("os.arch"));
 695  2986
                 Logger.getLogger(Buddi.class.getName()).info("Java VM version: " + System.getProperty("java.version"));
 696  
 
 697  
                 //Parse all the remaining options
 698  2986
                 Boolean usbKey = results.getBoolean("--usb");
 699  2986
                 String prefsLocation = results.getString("--prefs");
 700  2986
                 String font = results.getString("--font");
 701  2986
                 languagesFolder = results.getString("--languages");
 702  2986
                 pluginsFolder = results.getString("--plugins");
 703  
 
 704  2986
                 noAutoSave = results.getBoolean("--noautosave");
 705  2986
                 windowsInstaller = results.getBoolean("--windows-installer");
 706  2986
                 slackware = results.getBoolean("--slackware");
 707  2986
                 debian = results.getBoolean("--debian");
 708  2986
                 redhat = results.getBoolean("--redhat");
 709  2986
                 genericUnix = results.getBoolean("--unix");
 710  2986
                 reportsFolder = results.getString("--reports");
 711  
 
 712  
 
 713  2986
                 filesToLoad = new LinkedList<File>();
 714  2986
                 for (String s : results.getCommands()) {
 715  0
                         filesToLoad.add(new File(s));
 716  
                 }
 717  
 
 718  2986
                 Logger.getLogger(Buddi.class.getName()).finest("Files to load: " + filesToLoad);
 719  
 
 720  2986
                 String currentWorkingDir = System.getProperty("user.dir") + File.separator;
 721  
 
 722  
                 //Set some directories if USB mode is enabled.
 723  2986
                 if (usbKey != null && usbKey){
 724  0
                         if (languagesFolder == null)
 725  0
                                 languagesFolder = currentWorkingDir + Const.LANGUAGE_FOLDER;
 726  0
                         if (pluginsFolder == null)
 727  0
                                 pluginsFolder = currentWorkingDir + Const.PLUGIN_FOLDER;
 728  0
                         if (prefsLocation == null)
 729  0
                                 prefsLocation = currentWorkingDir + Const.PREFERENCE_FILE_NAME;
 730  
                 }
 731  
 
 732  
                 //Override the location of the Prefs file, if the -p flag is set.
 733  
                 // This MUST be called before the first PrefsMode.getInstance() 
 734  
                 // is called.
 735  2986
                 if (prefsLocation != null){
 736  0
                         PrefsModel.setPrefsFile(new File(prefsLocation));
 737  
                 }
 738  
 
 739  
                 //If we specify a different font, replace all font instances with it.
 740  
                 // This is useful for some locales, in which the default font
 741  
                 // won't work properly.
 742  2986
                 if (font != null){
 743  0
                         Enumeration<Object> keys = UIManager.getDefaults().keys();
 744  0
                         while (keys.hasMoreElements()) {
 745  0
                                 Object key = keys.nextElement();
 746  0
                                 Object value = UIManager.get(key);
 747  0
                                 if (value instanceof FontUIResource){
 748  0
                                         FontUIResource f = (FontUIResource) value;
 749  0
                                         UIManager.put(key, new FontUIResource(font, f.getStyle(), f.getSize()));
 750  
                                 }
 751  0
                         }  
 752  
                 }
 753  
 
 754  
                 //Let the user know where the working directory is, after
 755  
                 // we have set up logging properly.
 756  2986
                 Logger.getLogger(Buddi.class.getName()).info("Working directory: " + currentWorkingDir);
 757  
 
 758  
                 //Run any RunnablePlugins which we may have here.
 759  2986
                 for (BuddiRunnablePlugin plugin : (List<BuddiRunnablePlugin>) BuddiPluginFactory.getPlugins(BuddiRunnablePlugin.class)) {
 760  
                         try {
 761  0
                                 plugin.run();
 762  
                         }
 763  0
                         catch (RuntimeException re){
 764  0
                                 Logger.getLogger(Buddi.class.getName()).log(Level.SEVERE, "Runtime Exception encountered while starting plugin", re);
 765  0
                                 JOptionPane.showMessageDialog(null, "There was a problem starting the plugin " + plugin.getClass() + ".  Please send a copy of Buddi.log to the plugin author for debugging.");
 766  
                         }
 767  0
                         catch (Exception e){
 768  0
                                 Logger.getLogger(Buddi.class.getName()).log(Level.WARNING, "Exception encountered while starting plugin", e);
 769  0
                                 JOptionPane.showMessageDialog(null, "There was a problem starting the plugin " + plugin.getClass() + ".  Please send a copy of Buddi.log to the plugin author for debugging.");
 770  0
                         }
 771  
                 }
 772  
 
 773  
                 //Start the GUI in the proper thread
 774  2986
                 SwingUtilities.invokeLater(new Runnable() {
 775  
                         public void run() {
 776  2986
                                 launchGUI();
 777  2977
                         }
 778  
                 });
 779  2986
         }
 780  
 
 781  
         /**
 782  
          * Display any information you need to see on first version, such as 
 783  
          * donation requests, etc. 
 784  
          */
 785  
         private static void startVersionCheck(final MossFrame frame){
 786  2977
                 String[] warningButtons = new String[2];
 787  2977
                 warningButtons[0] = "Continue";
 788  2977
                 warningButtons[1] = "Quit";
 789  
                 
 790  
 //                int warningReply = JOptionPane.showOptionDialog(
 791  
 //                                frame,
 792  
 //                                "This version of Buddi includes major changes to transactions, and is probably\n" +
 793  
 //                                "not yet stable enough for production use.  USE THIS VERSION AT YOUR OWN RISK!!!\n\n" +
 794  
 //                                "Please report any bugs you encounter to Wyatt (wyatt.olson@gmail.com), or via the\n" +
 795  
 //                                "Buddi website.\n\n" +
 796  
 //                                "To repeat: There are very likely serious bugs with this version, and IT IS NOT\n" +
 797  
 //                                "RECOMMENDED FOR USE WITH REAL FINANCIAL DATA.  IF YOU USE IT, AND YOU\n" +
 798  
 //                                "LOSE YOUR DATA, DON'T COMPLAIN TO ME!",
 799  
 //                                "WARNING - Major Unstable Changes to Data and User Interface",
 800  
 //                                JOptionPane.YES_NO_OPTION,
 801  
 //                                JOptionPane.WARNING_MESSAGE,
 802  
 //                                null,
 803  
 //                                warningButtons,
 804  
 //                                warningButtons[1]
 805  
 //                                );
 806  
 //                if (warningReply != JOptionPane.YES_OPTION){
 807  
 //                        System.exit(0);
 808  
 //                }
 809  
                 
 810  2977
                 if (PrefsModel.getInstance().getLastVersion() == null 
 811  
                                 || !PrefsModel.getInstance().getLastVersion().equals(getVersion())){
 812  0
                         PrefsModel.getInstance().updateVersion();
 813  
 
 814  0
                         String[] buttons = new String[2];
 815  0
                         buttons[0] = TextFormatter.getTranslation(ButtonKeys.BUTTON_DONATE);
 816  0
                         buttons[1] = TextFormatter.getTranslation(ButtonKeys.BUTTON_NOT_NOW);
 817  
 
 818  0
                         int reply = JOptionPane.showOptionDialog(
 819  
                                         frame, 
 820  
                                         TextFormatter.getTranslation(BuddiKeys.MESSAGE_ASK_FOR_DONATION),
 821  
                                         TextFormatter.getTranslation(BuddiKeys.MESSAGE_ASK_FOR_DONATION_TITLE),
 822  
                                         JOptionPane.YES_NO_OPTION,
 823  
                                         JOptionPane.INFORMATION_MESSAGE,
 824  
                                         null,
 825  
                                         buttons,
 826  
                                         buttons[0]);
 827  
 
 828  0
                         if (reply == JOptionPane.YES_OPTION){
 829  
                                 try{
 830  0
                                         BrowserLauncher bl = new BrowserLauncher(null);
 831  0
                                         bl.openURLinBrowser(Const.DONATE_URL);
 832  
                                 }
 833  0
                                 catch (Exception e){
 834  0
                                         Logger.getLogger(Buddi.class.getName()).log(Level.WARNING, "Unknown Exception", e);
 835  0
                                 }
 836  
                         }
 837  
                 }
 838  2977
         }
 839  
 
 840  
         /**
 841  
          * Starts a thread which checks the Internet for any new versions.
 842  
          */
 843  
         public static void startUpdateCheck(final MossFrame frame){
 844  2977
                 if (PrefsModel.getInstance().isShowUpdateNotifications()){
 845  0
                         Thread updateThread = new Thread("Update Thread"){
 846  
                                 public void run() {
 847  
                                         try{
 848  
                                                 Proxy p;
 849  0
                                                 if (PrefsModel.getInstance().isShowProxySettings()){
 850  0
                                                         InetAddress proxyAddress = InetAddress.getByName(PrefsModel.getInstance().getProxyServer());
 851  0
                                                         InetSocketAddress socketAddress = new InetSocketAddress(proxyAddress, PrefsModel.getInstance().getPort()); 
 852  0
                                                         p = new Proxy(Proxy.Type.DIRECT, socketAddress);
 853  0
                                                 }
 854  
                                                 else {
 855  0
                                                         p = Proxy.NO_PROXY;
 856  
                                                 }
 857  
 
 858  0
                                                 URL mostRecentVersion = new URL(Const.PROJECT_URL + Const.VERSION_FILE);
 859  0
                                                 URLConnection connection = mostRecentVersion.openConnection(p);
 860  
 
 861  0
                                                 InputStream is = connection.getInputStream();
 862  
 
 863  
 
 864  0
                                                 Properties versions = new Properties();
 865  
 
 866  0
                                                 versions.load(is);
 867  
 
 868  0
                                                 PrefsModel.getInstance().setAvailableVersion(versions.getProperty(Const.BRANCH));
 869  
                                         }
 870  0
                                         catch (IOException ioe){
 871  0
                                                 Logger.getLogger(Buddi.class.getName()).log(Level.WARNING, "Unknown Exception", ioe);
 872  0
                                         }                                        
 873  0
                                 };
 874  
                         };
 875  
 
 876  0
                         updateThread.start();
 877  
                 }
 878  2977
         }
 879  
 
 880  
         /**
 881  
          * Checks for new updates, and notifies user if they are found.
 882  
          */
 883  
         public static void doUpdateCheck(final MossFrame frame){
 884  18
                 SwingWorker updateWorker = new SwingWorker(){
 885  
                         @Override
 886  
                         public Object construct() {
 887  
                                 try{
 888  
                                         Proxy p;
 889  18
                                         if (PrefsModel.getInstance().isShowProxySettings()){
 890  0
                                                 InetAddress proxyAddress = InetAddress.getByName(PrefsModel.getInstance().getProxyServer());
 891  0
                                                 InetSocketAddress socketAddress = new InetSocketAddress(proxyAddress, PrefsModel.getInstance().getPort()); 
 892  0
                                                 p = new Proxy(Proxy.Type.DIRECT, socketAddress);
 893  0
                                         }
 894  
                                         else {
 895  18
                                                 p = Proxy.NO_PROXY;
 896  
                                         }
 897  
 
 898  18
                                         URL mostRecentVersion = new URL(Const.PROJECT_URL + Const.VERSION_FILE);
 899  18
                                         URLConnection connection = mostRecentVersion.openConnection(p);
 900  
 
 901  18
                                         InputStream is = connection.getInputStream();
 902  
 
 903  
 
 904  18
                                         Properties versions = new Properties();
 905  
 
 906  18
                                         versions.load(is);
 907  
 
 908  18
                                         if (versions.get(Const.BRANCH) == null)
 909  0
                                                 return getVersion();
 910  
 
 911  18
                                         Version availableVersion = new Version(versions.get(Const.BRANCH).toString());
 912  18
                                         Version thisVersion = getVersion();
 913  
 
 914  18
                                         Logger.getLogger(Buddi.class.getName()).finest("This version: " + thisVersion);
 915  18
                                         Logger.getLogger(Buddi.class.getName()).finest("Available version: " + availableVersion);
 916  
 
 917  18
                                         if (thisVersion.compareTo(availableVersion) < 0)
 918  18
                                                 return availableVersion;
 919  
                                 }
 920  0
                                 catch (IOException ioe){
 921  0
                                         Logger.getLogger(Buddi.class.getName()).log(Level.WARNING, "Unknown Exception", ioe);
 922  
 
 923  0
                                         String[] options = new String[1];
 924  0
                                         options[0] = TextFormatter.getTranslation(ButtonKeys.BUTTON_OK);
 925  
 
 926  0
                                         JOptionPane.showOptionDialog(
 927  
                                                         frame, 
 928  
                                                         TextFormatter.getTranslation(BuddiKeys.MESSAGE_ERROR_CHECKING_FOR_UPDATES), 
 929  
                                                         TextFormatter.getTranslation(BuddiKeys.ERROR), 
 930  
                                                         JOptionPane.DEFAULT_OPTION,
 931  
                                                         JOptionPane.ERROR_MESSAGE,
 932  
                                                         null,
 933  
                                                         options,
 934  
                                                         options[0]);
 935  0
                                 }
 936  
 
 937  0
                                 return null;
 938  
                         }
 939  
 
 940  
                         @Override
 941  
                         public void finished() {
 942  18
                                 if (get() != null){
 943  18
                                         String[] buttons = new String[2];
 944  18
                                         buttons[0] = TextFormatter.getTranslation(ButtonKeys.BUTTON_DOWNLOAD);
 945  18
                                         buttons[1] = TextFormatter.getTranslation(ButtonKeys.BUTTON_CANCEL);
 946  
 
 947  18
                                         int reply = JOptionPane.showOptionDialog(
 948  
                                                         frame, 
 949  
                                                         TextFormatter.getTranslation(BuddiKeys.NEW_VERSION_MESSAGE)
 950  
                                                         + " " + get() + "\n"
 951  
                                                         + TextFormatter.getTranslation(BuddiKeys.NEW_VERSION_MESSAGE_2),
 952  
                                                         TextFormatter.getTranslation(BuddiKeys.NEW_VERSION),
 953  
                                                         JOptionPane.YES_NO_OPTION,
 954  
                                                         JOptionPane.INFORMATION_MESSAGE,
 955  
                                                         null,
 956  
                                                         buttons,
 957  
                                                         buttons[0]);
 958  
 
 959  8
                                         if (reply == JOptionPane.YES_OPTION){
 960  
                                                 String fileLocation;
 961  3
                                                 if (Const.BRANCH.equals(Const.STABLE))
 962  3
                                                         fileLocation = Const.DOWNLOAD_URL_STABLE;
 963  
                                                 else
 964  0
                                                         fileLocation = Const.DOWNLOAD_URL_UNSTABLE;
 965  
 
 966  
                                                 //Link to the correct download by default.
 967  3
                                                 if (OperatingSystemUtil.isMac())
 968  0
                                                         fileLocation += Const.DOWNLOAD_TYPE_OSX;
 969  3
                                                 else if (OperatingSystemUtil.isWindows()){
 970  0
                                                         if (isWindowsInstaller())
 971  0
                                                                 fileLocation += Const.DOWNLOAD_TYPE_WINDOWS_INSTALLER;
 972  
                                                         else
 973  0
                                                                 fileLocation += Const.DOWNLOAD_TYPE_WINDOWS;
 974  
                                                 }
 975  
                                                 else {
 976  
                                                         //Check for any specific distributions here
 977  3
                                                         if (Buddi.isDebian())
 978  0
                                                                 fileLocation += Const.DOWNLOAD_TYPE_DEBIAN;
 979  3
                                                         else if (Buddi.isSlackware())
 980  0
                                                                 fileLocation += Const.DOWNLOAD_TYPE_SLACKWARE;
 981  3
                                                         else if (Buddi.isRedhat())
 982  0
                                                                 fileLocation += Const.DOWNLOAD_TYPE_REDHAT;
 983  3
                                                         else if (Buddi.isUnix())
 984  0
                                                                 fileLocation += Const.DOWNLOAD_TYPE_UNIX;
 985  
                                                         else
 986  3
                                                                 fileLocation += Const.DOWNLOAD_TYPE_GENERIC;
 987  
                                                 }
 988  
 
 989  
                                                 try{
 990  3
                                                         BrowserLauncher bl = new BrowserLauncher(null);
 991  3
                                                         bl.openURLinBrowser(fileLocation);
 992  
                                                 }
 993  0
                                                 catch (Exception e){
 994  0
                                                         Logger.getLogger(Buddi.class.getName()).log(Level.WARNING, "Unknown Exception", e);
 995  3
                                                 }
 996  
                                         }
 997  8
                                 }
 998  
                                 //There was no updates - if we want a confirmation, show it
 999  
                                 else {
 1000  0
                                         String[] options = new String[1];
 1001  0
                                         options[0] = TextFormatter.getTranslation(ButtonKeys.BUTTON_OK);
 1002  
 
 1003  0
                                         JOptionPane.showOptionDialog(
 1004  
                                                         frame, 
 1005  
                                                         TextFormatter.getTranslation(BuddiKeys.MESSAGE_NO_NEW_VERSION), 
 1006  
                                                         TextFormatter.getTranslation(BuddiKeys.MESSAGE_NO_NEW_VERSION_TITLE), 
 1007  
                                                         JOptionPane.DEFAULT_OPTION,
 1008  
                                                         JOptionPane.INFORMATION_MESSAGE,
 1009  
                                                         null,
 1010  
                                                         options,
 1011  
                                                         options[0]);
 1012  
                                 }
 1013  
 
 1014  8
                                 super.finished();
 1015  8
                         }
 1016  
                 };
 1017  
 
 1018  18
                 if (Const.DEVEL) Logger.getLogger(Buddi.class.getName()).finest("Starting update checking...");
 1019  18
                 updateWorker.start();
 1020  18
         }
 1021  
 
 1022  
 
 1023  
         public static void sendBugReport(Document... models){
 1024  
 //                StringBuilder crashLog = new StringBuilder();
 1025  
 //                crashLogger.getLogger().append("\n---Starting Preferences---\n");
 1026  
 //                crashLogger.getLogger().append(PrefsModel.getInstance().saveToString());
 1027  
 //                crashLogger.getLogger().append("---Finished Preferences---\n\n");
 1028  
 
 1029  
 //                if (models != null){
 1030  
 //                for (Document m : models) {
 1031  
 //                ByteArrayOutputStream baos = new ByteArrayOutputStream();
 1032  
 //                try {
 1033  
 //                m.saveToStream(baos);
 1034  
 
 1035  
 //                crashLogger.getLogger().append("---Starting Data File---\n");
 1036  
 //                crashLogger.getLogger().append(baos.toString());
 1037  
 //                crashLogger.getLogger().append("---Finished Data File---\n\n");
 1038  
 //                }
 1039  
 //                catch (DocumentSaveException dse){
 1040  
 //                crashLogger.getLogger().append("---Starting Data File---\n");
 1041  
 //                crashLogger.getLogger().append("Error: Could not save to stream:");
 1042  
 //                crashLogger.getLogger().append(dse.getMessage());
 1043  
 //                crashLogger.getLogger().append("---Finished Data File---\n\n");                                        
 1044  
 //                }
 1045  
 //                }
 1046  
 //                }
 1047  
 
 1048  
 //                if (logFile != null){
 1049  
 //                try{
 1050  
 //                BufferedReader logReader = new BufferedReader(new FileReader(logFile));
 1051  
 //                crashLogger.getLogger().append("---Starting Log File (" + logFile.getAbsolutePath() + ")---\n");
 1052  
 //                String temp;
 1053  
 //                while ((temp = logReader.readLine()) != null)
 1054  
 //                crashLogger.getLogger().append(temp).append("\n");
 1055  
 //                crashLogger.getLogger().append("---Finished Log File---\n");
 1056  
 //                }
 1057  
 //                catch (IOException ioe){}
 1058  
 //                }
 1059  
 
 1060  
 
 1061  
 //                if (PrefsModel.getInstance().isSendCrashReports()){
 1062  
 //                try {
 1063  
 //                BrowserLauncher bl = new BrowserLauncher();
 1064  
 //                bl.openURLinBrowser("mailto:wyatt.olson@gmail.com?subject=" 
 1065  
 //                + URLEncoder.encode("Buddi Crash Report", "UTF-8").replaceAll("\\+", "%20") 
 1066  
 //                + "&body="
 1067  
 //                + URLEncoder.encode(
 1068  
 //                "There has been a serious problem encountered in Buddi, " +
 1069  
 //                "and Buddi has closed.  It is recommended that you send a " +
 1070  
 //                "crash report to the program author (Wyatt Olson <wyatt.olson@gmail.com>) " +
 1071  
 //                "to help him troubleshoot the problem.  The following components may " +
 1072  
 //                "be included in the crash report:\n\t-Contents of your Preferences " +
 1073  
 //                "file,\n\t-Contents of all open Data files\n\t-Contents of the Buddi " +
 1074  
 //                "log file\n\nThese components are included as text in the body below, " +
 1075  
 //                "clearly marked between tags such as '---Starting Preferences---' " +
 1076  
 //                "and '---Finished Preferences---'.  If for privacy or other reasons you" +
 1077  
 //                " wish to remove one or more of these components, feel free to do so." +
 1078  
 //                "\n\nIf you use a different mail program (such as a Web based email " +
 1079  
 //                "program), plese copy the entire contents of this email to that program, " +
 1080  
 //                "and send it to Wyatt.\n\nIf you do not wish to send this crash report at " +
 1081  
 //                "all, simply close this window.  You can disable sending future crash " + 
 1082  
 //                "reports in Buddi's Preferences.\n\n\n"
 1083  
 //                + crashLogger.getLogger().toString()
 1084  
 
 1085  
 //                , 
 1086  
 //                "UTF-8").replaceAll("\\+", "%20"));
 1087  
 //                }
 1088  
 //                catch (Exception e){
 1089  
 //                Logger.getLogger().emergency("Unable to send crash email.");
 1090  
 //                }
 1091  
 //                }
 1092  
 
 1093  
 //                Logger.getLogger().critical(crashLogger.getLogger().toString());
 1094  87
         }
 1095  
 
 1096  
         private static void extractFile(File fileToLoad){
 1097  
                 try {
 1098  
                         InputStream is;
 1099  0
                         BuddiCryptoFactory factory = new BuddiCryptoFactory();
 1100  0
                         char[] password = null;
 1101  
 
 1102  
                         //Loop until the user gets the password correct, hits cancel, 
 1103  
                         // or some other error occurs.
 1104  
                         while (true) {
 1105  
                                 try {
 1106  0
                                         is = factory.getDecryptedStream(new FileInputStream(fileToLoad), password);
 1107  0
                                         OutputStream os = new FileOutputStream(new File(fileToLoad.getAbsolutePath() + ".xml"));
 1108  0
                                         StreamUtil.copyStream(is, os);
 1109  
 
 1110  0
                                         os.flush();
 1111  0
                                         os.close();
 1112  0
                                         is.close();                                        
 1113  
 
 1114  0
                                         System.exit(0);
 1115  
                                 }
 1116  0
                                 catch (IncorrectPasswordException ipe){
 1117  
                                         //The password was not correct.  Prompt for a new one.
 1118  0
                                         BuddiPasswordDialog passwordDialog = new BuddiPasswordDialog();
 1119  0
                                         password = passwordDialog.askForPassword(false, true);
 1120  
 
 1121  
                                         //User hit cancel.  Exit.
 1122  0
                                         if (password == null)
 1123  0
                                                 System.exit(0);
 1124  
                                 }
 1125  0
                                 catch (Exception e){
 1126  0
                                         e.printStackTrace();
 1127  0
                                         System.exit(1);
 1128  0
                                 }
 1129  
                         }
 1130  
                 }
 1131  0
                 catch (Exception e){
 1132  0
                         e.printStackTrace();
 1133  0
                         System.exit(1);
 1134  
                 }
 1135  
 
 1136  0
                 System.exit(0);
 1137  0
         }
 1138  
 }