[jsword-svn] r1120 - in trunk: bibledesktop/etc/images bibledesktop/src/main/resources jsword/src/main/java/org/crosswire/jsword/book/install/sword jsword/src/main/java/org/crosswire/jsword/book/sword jsword/src/main/java/org/crosswire/jsword/util

dmsmith at www.crosswire.org dmsmith at www.crosswire.org
Sat Aug 26 10:35:29 MST 2006


Author: dmsmith
Date: 2006-08-26 10:35:11 -0700 (Sat, 26 Aug 2006)
New Revision: 1120

Added:
   trunk/bibledesktop/etc/images/BibleDesktop.icns
   trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBookPath.java
Modified:
   trunk/bibledesktop/src/main/resources/config.properties
   trunk/bibledesktop/src/main/resources/config.xml
   trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/AbstractSwordInstaller.java
   trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBookDriver.java
   trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordUtil.java
   trunk/jsword/src/main/java/org/crosswire/jsword/util/Project.java
Log:
Changed sword path to be more friendly on Mac and Windows.

Added: trunk/bibledesktop/etc/images/BibleDesktop.icns
===================================================================
(Binary files differ)


Property changes on: trunk/bibledesktop/etc/images/BibleDesktop.icns
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/bibledesktop/src/main/resources/config.properties
===================================================================
--- trunk/bibledesktop/src/main/resources/config.properties	2006-08-25 17:30:52 UTC (rev 1119)
+++ trunk/bibledesktop/src/main/resources/config.properties	2006-08-26 17:35:11 UTC (rev 1120)
@@ -36,8 +36,8 @@
 BibleDisplay.ConfigurableFont.help=The font to be used to display books.
 BibleDisplay.AntiAliasDisplay.path=Bible Display.Font Smoothing
 BibleDisplay.AntiAliasDisplay.help=Font smoothing can be slow, but can help the appearance of some fonts.
-SwordBook.BookSearchPath.path=Sword Books.Book Search Path
-SwordBook.BookSearchPath.help=Where should we look for SWORD Project books.
+SwordBook.BookSearchPath.path=Sword Books.Additional Book locations
+SwordBook.BookSearchPath.help=Additional places to look for SWORD books.
 SwordBook.DownloadDirectory.path=Sword Books.Download Directory
 SwordBook.DownloadDirectory.help=Where should we store newly downloaded books.
 Remote.RemoteHost.path=Remote.Remote Host

Modified: trunk/bibledesktop/src/main/resources/config.xml
===================================================================
--- trunk/bibledesktop/src/main/resources/config.xml	2006-08-25 17:30:52 UTC (rev 1119)
+++ trunk/bibledesktop/src/main/resources/config.xml	2006-08-26 17:35:11 UTC (rev 1120)
@@ -153,11 +153,11 @@
   </option>
 
   <option key="SwordBook.BookSearchPath" type="path">
-    <introspect class="org.crosswire.jsword.book.sword.SwordBookDriver" property="SwordPath"/>
+    <introspect class="org.crosswire.jsword.book.sword.SwordBookPath" property="AugmentPath"/>
   </option>
 
   <option key="SwordBook.DownloadDirectory" type="directory">
-    <introspect class="org.crosswire.jsword.book.sword.SwordBookDriver" property="DownloadDir"/>
+    <introspect class="org.crosswire.jsword.book.sword.SwordBookPath" property="DownloadDir"/>
   </option>
 
 <!-- Currently not used

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/AbstractSwordInstaller.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/AbstractSwordInstaller.java	2006-08-25 17:30:52 UTC (rev 1119)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/AbstractSwordInstaller.java	2006-08-26 17:35:11 UTC (rev 1120)
@@ -50,6 +50,7 @@
 import org.crosswire.jsword.book.sword.SwordBookDriver;
 import org.crosswire.jsword.book.sword.SwordBookMetaData;
 import org.crosswire.jsword.book.sword.SwordConstants;
+import org.crosswire.jsword.book.sword.SwordBookPath;
 import org.crosswire.jsword.util.Project;
 
 import com.ice.tar.TarEntry;
@@ -100,7 +101,7 @@
      */
     public boolean isNewer(Book book)
     {
-        File dldir = SwordBookDriver.getDownloadDir();
+        File dldir = SwordBookPath.getDownloadDir();
 
         SwordBookMetaData sbmd = (SwordBookMetaData) book.getBookMetaData();
         File conf = new File(dldir, sbmd.getConfPath());
@@ -193,7 +194,7 @@
 
                     // Once the unzipping is started, we need to continue
                     job.setInterruptable(false);
-                    File dldir = SwordBookDriver.getDownloadDir();
+                    File dldir = SwordBookPath.getDownloadDir();
                     if (!job.isFinished())
                     {
                         IOUtil.unpackZip(NetUtil.getAsFile(temp), dldir);

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBookDriver.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBookDriver.java	2006-08-25 17:30:52 UTC (rev 1119)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBookDriver.java	2006-08-26 17:35:11 UTC (rev 1120)
@@ -22,17 +22,11 @@
 package org.crosswire.jsword.book.sword;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FilenameFilter;
-import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
-import java.util.Properties;
 
 import org.crosswire.common.util.FileUtil;
 import org.crosswire.common.util.Logger;
-import org.crosswire.common.util.StringUtil;
 import org.crosswire.jsword.book.Book;
 import org.crosswire.jsword.book.BookDriver;
 import org.crosswire.jsword.book.BookException;
@@ -41,10 +35,9 @@
 import org.crosswire.jsword.index.IndexManager;
 import org.crosswire.jsword.index.IndexManagerFactory;
 import org.crosswire.jsword.index.IndexStatus;
-import org.crosswire.jsword.util.Project;
 
 /**
- * This represents all of the SwordBibles.
+ * This represents all of the Sword Books (aka modules).
  *
  * @see gnu.lgpl.License for license details.
  *      The copyright to this program is held by it's authors.
@@ -77,7 +70,7 @@
 
         List valid = new ArrayList();
 
-        // Loop through the dirs in the lookup path
+        File[] dirs = SwordBookPath.getSwordPath();
         for (int j = 0; j < dirs.length; j++)
         {
             getBooks(valid, dirs[j]);
@@ -88,40 +81,44 @@
         return (Book[]) valid.toArray(new Book[valid.size()]);
     }
 
-    private void getBooks(List valid, File moduleDir)
+    private void getBooks(List valid, File bookDir)
     {
-        File mods = new File(moduleDir, SwordConstants.DIR_CONF);
+        File mods = new File(bookDir, SwordConstants.DIR_CONF);
         if (mods.isDirectory())
         {
-            String[] bookdirs = mods.list(new CustomFilenameFilter());
-    
+            String[] bookConfs = SwordBookPath.getBookList(mods);
+
             // Loop through the entries in this mods.d directory
-            for (int i = 0; i < bookdirs.length; i++)
+            for (int i = 0; i < bookConfs.length; i++)
             {
-                String bookdir = bookdirs[i];
+                String bookConf = bookConfs[i];
                 try
                 {
-                    File configfile = new File(mods, bookdir);
-                    String internal = bookdir;
+                    File configfile = new File(mods, bookConf);
+                    String internal = bookConf;
                     if (internal.endsWith(SwordConstants.EXTENSION_CONF))
                     {
                         internal = internal.substring(0, internal.length() - 5);
                     }
                     SwordBookMetaData sbmd = new SwordBookMetaData(configfile, internal);
                     sbmd.setDriver(this);
-    
-                    Book book = createBook(sbmd, moduleDir);
-                    valid.add(book);
-    
-                    IndexManager imanager = IndexManagerFactory.getIndexManager();
-                    if (imanager.isIndexed(book))
+
+                    // Only take the first "installation" of the Book
+                    Book book = createBook(sbmd, bookDir);
+                    if (!valid.contains(book))
                     {
-                        sbmd.setIndexStatus(IndexStatus.DONE);
+                        valid.add(book);
+
+                        IndexManager imanager = IndexManagerFactory.getIndexManager();
+                        if (imanager.isIndexed(book))
+                        {
+                            sbmd.setIndexStatus(IndexStatus.DONE);
+                        }
+                        else
+                        {
+                            sbmd.setIndexStatus(IndexStatus.UNDONE);
+                        }
                     }
-                    else
-                    {
-                        sbmd.setIndexStatus(IndexStatus.UNDONE);
-                    }
                 }
                 catch (Exception ex)
                 {
@@ -142,8 +139,8 @@
     public boolean isDeletable(Book dead)
     {
         SwordBookMetaData sbmd = (SwordBookMetaData) dead.getBookMetaData();
-        File downloadDir = SwordBookDriver.getDownloadDir();
-        File confFile = new File(downloadDir, sbmd.getConfPath());
+        File dlDir = SwordBookPath.getDownloadDir();
+        File confFile = new File(dlDir, sbmd.getConfPath());
 
         // We can only uninstall what we download into our download dir.
         return confFile.exists();
@@ -156,8 +153,8 @@
     public void delete(Book dead) throws BookException
     {
         SwordBookMetaData sbmd = (SwordBookMetaData) dead.getBookMetaData();
-        File downloadDir = SwordBookDriver.getDownloadDir();
-        File confFile = new File(downloadDir, sbmd.getConfPath());
+        File dlDir = SwordBookPath.getDownloadDir();
+        File confFile = new File(dlDir, sbmd.getConfPath());
 
         // We can only uninstall what we download into our download dir.
         if (!confFile.exists())
@@ -165,7 +162,7 @@
             throw new BookException(Msg.DELETE_FAILED, new Object [] {confFile});
         }
 
-        File bookDir = new File(downloadDir, sbmd.getBookPath());
+        File bookDir = new File(dlDir, sbmd.getBookPath());
 
         // Delete the conf
         List failures = FileUtil.delete(confFile);
@@ -231,314 +228,11 @@
     }
 
     /**
-     * Accessor for the Sword directory
-     * @param theNewDirs The new Sword directory
-     * @throws BookException
-     */
-    public static void setSwordPath(File[] theNewDirs) throws BookException
-    {
-        File[] newDirs = theNewDirs;
-        newDirs = validateSwordPath(newDirs);
-        if (newDirs == null)
-        {
-            return;
-        }
-
-        SwordBookDriver.dirs = newDirs;
-
-        // Now we need to (re)register ourselves
-        Books.installed().registerDriver(INSTANCE);
-    }
-
-    /**
-     * validateSwordPath maintains the invariant that the download
-     * location is first in the list. If null or an empty array
-     * is passed then the defaultList is used.
-     * @param theFiles
-     * @return null if the list is not to be used, otherwise it returns the list.
-     */
-    private static File[] validateSwordPath(File[] theFiles)
-    {
-        File[] files = theFiles;
-        // Get the current download file location
-        File downloadDir = SwordBookDriver.dirs[0];
-        boolean useDefaultPaths = false;
-
-        // If the new paths are empty then guess ...
-        if (files == null || files.length == 0)
-        {
-            files = getDefaultPaths();
-            useDefaultPaths = true;
-        }
-
-        // If there is no change then there is nothing to do
-        if (Arrays.equals(files, SwordBookDriver.dirs))
-        {
-            return null;
-        }
-
-        if (useDefaultPaths)
-        {
-            log.warn("No paths set, using defaults"); //$NON-NLS-1$
-        }
-
-        // Maintain that downloadDir is in the array and that it is first.
-        else if (!files[0].equals(downloadDir))
-        {
-            // Find it
-            int pos = -1;
-            for (int i = 0; i < files.length; i++)
-            {
-                if (downloadDir.equals(files[i]))
-                {
-                    pos = i;
-                    break;
-                }
-            }
-
-            // If it is not in the list then add it
-            if (pos == -1)
-            {
-                File[] temp = new File[files.length + 1];
-                temp[0] = downloadDir;
-                for (int i = 0; i < files.length; i++)
-                {
-                    temp[i + 1] = files[i];
-                }
-                files = temp;
-            }
-            else
-            {
-                // move downloadDir to the front
-                for (int i = pos; i > 0; i--)
-                {
-                    files[pos] = files[pos - 1];
-                }
-                files[0] = downloadDir;
-            }
-        }
-
-        return files;
-    }
-
-    /**
-     * Accessor for the Sword directory
-     * @return The new Sword directory
-     */
-    public static File[] getSwordPath()
-    {
-        return dirs;
-    }
-
-    /**
-     * Have a guess at where mods.d might be found.
-     * Remember all the locations.
-     */
-    private static File[] getDefaultPaths()
-    {
-        List reply = new ArrayList();
-
-        String home = System.getProperty(PROPERTY_USER_HOME);
-
-        // Is sword.conf in the current diretory?
-        readSwordConf(reply, "."); //$NON-NLS-1$
-        
-        // mods.d in the current directory?
-        testDefaultPath(reply, "."); //$NON-NLS-1$
-
-        // how about in the library, just next door?
-        testDefaultPath(reply, ".." + File.separator + DIR_SWORD_LIBRARY); //$NON-NLS-1$
-
-        // if there is a property set for the sword home directory
-        String swordhome = System.getProperty(PROPERTY_SWORD_HOME);
-        if (swordhome != null)
-        {
-            testDefaultPath(reply, swordhome);
-
-            // how about in the library, just next door?
-            testDefaultPath(reply, swordhome + File.separator + ".." + File.separator + DIR_SWORD_LIBRARY); //$NON-NLS-1$
-        }
-
-        if (System.getProperty("os.name").startsWith("Windows")) //$NON-NLS-1$ //$NON-NLS-2$
-        {
-            testDefaultPath(reply, DIR_WINDOWS_DEFAULT);
-            // how about in the library, just next door?
-            testDefaultPath(reply, DIR_WINDOWS_DEFAULT + File.separator + ".." + File.separator + DIR_SWORD_LIBRARY); //$NON-NLS-1$
-        }
-
-        // .sword in the users home directory?
-        readSwordConf(reply, home + File.separator + DIR_SWORD_CONF);
-
-        // Check for sword.conf in the usual places
-        String [] sysconfigPaths = StringUtil.split(DIR_SWORD_GLOBAL_CONF, ':');
-        for (int i = 0; i < sysconfigPaths.length; i++)
-        {
-            readSwordConf(reply, sysconfigPaths[i]);
-        }
-
-        // finally look for mods.d in ~/.sword
-        testDefaultPath(reply, home + File.separator + DIR_SWORD_CONF);
-
-        // .jsword in the users home directory is the last location
-        reply.add(new File(home + File.separator + Project.DIR_PROJECT));
-
-        return (File[]) reply.toArray(new File[reply.size()]);
-    }
-
-    private static void readSwordConf(List reply, File swordConfDir)
-    {
-        File sysconfig = new File(swordConfDir, SWORD_GLOBAL_CONF);
-        if (sysconfig.canRead())
-        {
-            try
-            {
-                Properties prop = new Properties();
-                prop.load(new FileInputStream(sysconfig));
-                String datapath = prop.getProperty(DATA_PATH);
-                testDefaultPath(reply, datapath);
-                datapath = prop.getProperty(AUGMENT_PATH);
-                testDefaultPath(reply, datapath);
-            }
-            catch (IOException ex)
-            {
-                log.warn("Failed to read system config file", ex); //$NON-NLS-1$
-            }
-        }
-    }
-
-    private static void readSwordConf(List reply, String swordConfDir)
-    {
-        readSwordConf(reply, new File(swordConfDir));
-    }
-
-    /**
-     * Check to see if the given directory is a Sword mods.d directory
-     * and then add it to the list if it is.
-     */
-    private static void testDefaultPath(List reply, File path)
-    {
-        if (path == null)
-        {
-            return;
-        }
-
-        File mods = new File(path, SwordConstants.DIR_CONF);
-        if (mods.isDirectory() && mods.canRead())
-        {
-            reply.add(path);
-        }
-    }
-
-    /**
-     * Check to see if the given directory is a Sword mods.d directory
-     * and then add it to the list if it is.
-     */
-    private static void testDefaultPath(List reply, String path)
-    {
-        if (path == null)
-        {
-            return;
-        }
-
-        testDefaultPath(reply, new File(path));
-    }
-
-    /**
-     * @return Returns the download directory.
-     */
-    public static File getDownloadDir()
-    {
-        return dirs[0];
-    }
-
-    /**
-     * @param downloadDir The download directory to set.
-     */
-    public static void setDownloadDir(File downloadDir)
-    {
-        if (!downloadDir.getPath().equals("")) //$NON-NLS-1$
-        {
-            dirs[0] = downloadDir;
-            log.debug("Setting sword download directory to: " + downloadDir); //$NON-NLS-1$
-        }
-    }
-
-    /**
-     * Check that the directories in the version directory really
-     * represent versions.
-     */
-    static class CustomFilenameFilter implements FilenameFilter
-    {
-        /* (non-Javadoc)
-         * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
-         */
-        public boolean accept(File parent, String name)
-        {
-            return !name.startsWith(PREFIX_GLOBALS) && name.endsWith(SwordConstants.EXTENSION_CONF);
-        }
-    }
-
-    /**
-     * Default windows installation directory
-     */
-    private static final String DIR_WINDOWS_DEFAULT = "C:\\Program Files\\CrossWire\\The SWORD Project"; //$NON-NLS-1$
-
-    /**
-     * Library may be a sibling of DIR_WINDOWS_DEFAULT or SWORD_HOME or CWD
-     */
-    private static final String DIR_SWORD_LIBRARY = "library"; //$NON-NLS-1$
-
-    /**
-     * Users config directory for Sword in Unix
-     */
-    private static final String DIR_SWORD_CONF = ".sword"; //$NON-NLS-1$
-
-    /**
-     * Sword global config file
-     */
-    private static final String SWORD_GLOBAL_CONF = "sword.conf"; //$NON-NLS-1$
-
-    /**
-     * Sword global config file locations
-     */
-    private static final String DIR_SWORD_GLOBAL_CONF = "/etc:/usr/local/etc"; //$NON-NLS-1$
-
-    /**
-     * Sword global config file's path to where mods can be found
-     */
-    private static final String DATA_PATH = "DataPath"; //$NON-NLS-1$
-
-    /**
-     * Sword global config file's path to where mods can be found
-     */
-    private static final String AUGMENT_PATH = "AugmentPath"; //$NON-NLS-1$
-
-    /**
-     * System property for sword home directory
-     */
-    private static final String PROPERTY_SWORD_HOME = "sword.home"; //$NON-NLS-1$
-
-    /**
-     * Java system property for users home directory
-     */
-    private static final String PROPERTY_USER_HOME = "user.home"; //$NON-NLS-1$
-
-    /**
-     * File prefix for config file
-     */
-    private static final String PREFIX_GLOBALS = "globals."; //$NON-NLS-1$
-
-    /**
      * A shared instance of this driver.
      */
     private static final BookDriver INSTANCE = new SwordBookDriver();
 
     /**
-     * The directory URL
-     */
-    private static File[] dirs = getDefaultPaths();
-
-    /**
      * The log stream
      */
     private static final Logger log = Logger.getLogger(SwordBookDriver.class);

Added: trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBookPath.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBookPath.java	2006-08-25 17:30:52 UTC (rev 1119)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBookPath.java	2006-08-26 17:35:11 UTC (rev 1120)
@@ -0,0 +1,449 @@
+/**
+ * Distribution License:
+ * JSword is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License, version 2.1 as published by
+ * the Free Software Foundation. This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * The License is available on the internet at:
+ *       http://www.gnu.org/copyleft/lgpl.html
+ * or by writing to:
+ *      Free Software Foundation, Inc.
+ *      59 Temple Place - Suite 330
+ *      Boston, MA 02111-1307, USA
+ *
+ * Copyright: 2005
+ *     The copyright to this program is held by it's authors.
+ *
+ * ID: $Id: SwordBookDriver.java 1117 2006-08-15 16:41:29 -0400 (Tue, 15 Aug 2006) dmsmith $
+ */
+package org.crosswire.jsword.book.sword;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.crosswire.common.util.Logger;
+import org.crosswire.common.util.StringUtil;
+import org.crosswire.jsword.book.BookException;
+import org.crosswire.jsword.book.Books;
+import org.crosswire.jsword.util.Project;
+
+/**
+ * This represents all of the Sword Books (aka modules).
+ *
+ * @see gnu.lgpl.License for license details.
+ *      The copyright to this program is held by it's authors.
+ * @author Joe Walker [joe at eireneh dot com]
+ * @author DM Smith [dmsmith555 at yahoo dot com]
+ */
+public class SwordBookPath
+{
+    /**
+     * Some basic name initialization
+     */
+    private SwordBookPath()
+    {
+    }
+
+    /**
+     * Accessor for the Sword directory
+     * @param theNewDirs The new Sword directory
+     * @throws BookException
+     */
+    public static void setAugmentPath(File[] theNewDirs) throws BookException
+    {
+        File[] newDirs = theNewDirs;
+        if (newDirs == null)
+        {
+            return;
+        }
+
+        SwordBookPath.augmentPath = newDirs;
+
+        // Now we need to (re)register ourselves
+        Books.installed().registerDriver(SwordBookDriver.instance());
+    }
+
+    /**
+     * Accessor for the Sword directory
+     * @return The new Sword directory
+     */
+    public static File[] getAugmentPath()
+    {
+        return augmentPath;
+    }
+
+    /**
+     * Obtain a prioritized path of Book locations.
+     * This contains the downloadDir as the first location,
+     * the user's augment path and finally all the discovered
+     * standard locations.
+     * 
+     * @return the array of Book locations.
+     */
+    public static File[] getSwordPath()
+    {
+        ArrayList swordPath = new ArrayList();
+
+        // The first place to look for Books
+        swordPath.add(downloadDir);
+
+        // Then all the user's augments
+        if (augmentPath != null)
+        {
+            for (int i = 0; i < augmentPath.length; i++)
+            {
+                File path = augmentPath[i];
+                if (!swordPath.contains(path))
+                {
+                    swordPath.add(path);
+                }
+            }
+        }
+
+        File[] defaultPath = getDefaultPaths();
+        // Then all the user's bookDirs
+        if (defaultPath != null)
+        {
+            for (int i = 0; i < defaultPath.length; i++)
+            {
+                File path = defaultPath[i];
+                if (!swordPath.contains(path))
+                {
+                    swordPath.add(path);
+                }
+            }
+        }
+
+        return (File[]) swordPath.toArray(new File[swordPath.size()]);
+    }
+
+    public static String[] getBookList(File bookDir)
+    {
+        return bookDir.list(new CustomFilenameFilter());
+    }
+
+    /**
+     * Search all of the "standard" Sword locations for Books.
+     * Remember all the locations.
+     */
+    private static File[] getDefaultPaths()
+    {
+        // If possible migrate the old location to the new one
+        migrateBookDir();
+
+        List bookDirs = new ArrayList();
+
+        String home = System.getProperty(PROPERTY_USER_HOME);
+
+        // Is sword.conf in the current diretory?
+        readSwordConf(bookDirs, "."); //$NON-NLS-1$
+
+        // mods.d in the current directory?
+        testDefaultPath(bookDirs, "."); //$NON-NLS-1$
+
+        // how about in the library, just next door?
+        testDefaultPath(bookDirs, ".." + File.separator + DIR_SWORD_LIBRARY); //$NON-NLS-1$
+
+        // if there is a property set for the sword home directory
+        String swordhome = System.getProperty(PROPERTY_SWORD_HOME);
+        if (swordhome != null)
+        {
+            testDefaultPath(bookDirs, swordhome);
+
+            // how about in the library, just next door?
+            testDefaultPath(bookDirs, swordhome + File.separator + ".." + File.separator + DIR_SWORD_LIBRARY); //$NON-NLS-1$
+        }
+
+        if (System.getProperty("os.name").startsWith("Windows")) //$NON-NLS-1$ //$NON-NLS-2$
+        {
+            testDefaultPath(bookDirs, DIR_WINDOWS_DEFAULT);
+            // how about in the library, just next door?
+            testDefaultPath(bookDirs, DIR_WINDOWS_DEFAULT + File.separator + ".." + File.separator + DIR_SWORD_LIBRARY); //$NON-NLS-1$
+        }
+
+        // .sword in the users home directory?
+        readSwordConf(bookDirs, home + File.separator + DIR_SWORD_CONF);
+
+        // Check for sword.conf in the usual places
+        String [] sysconfigPaths = StringUtil.split(DIR_SWORD_GLOBAL_CONF, ':');
+        for (int i = 0; i < sysconfigPaths.length; i++)
+        {
+            readSwordConf(bookDirs, sysconfigPaths[i]);
+        }
+
+        URL userDataArea = Project.instance().getUserProjectDir(DIR_SWORD_CONF, DIR_SWORD_CONF_ALT);
+
+        // Check look for mods.d in the sword user data area
+        testDefaultPath(bookDirs, new File(userDataArea.getFile()));
+
+        // If the migration did not work then use the old area
+        testDefaultPath(bookDirs, new File(Project.instance().getUserProjectDir().getFile()));
+
+        return (File[]) bookDirs.toArray(new File[bookDirs.size()]);
+    }
+
+    private static void readSwordConf(List bookDirs, File swordConfDir)
+    {
+        File sysconfig = new File(swordConfDir, SWORD_GLOBAL_CONF);
+        if (sysconfig.canRead())
+        {
+            try
+            {
+                Properties prop = new Properties();
+                prop.load(new FileInputStream(sysconfig));
+                String datapath = prop.getProperty(DATA_PATH);
+                testDefaultPath(bookDirs, datapath);
+                datapath = prop.getProperty(AUGMENT_PATH);
+                testDefaultPath(bookDirs, datapath);
+            }
+            catch (IOException ex)
+            {
+                log.warn("Failed to read system config file", ex); //$NON-NLS-1$
+            }
+        }
+    }
+
+    private static void readSwordConf(List bookDirs, String swordConfDir)
+    {
+        readSwordConf(bookDirs, new File(swordConfDir));
+    }
+
+    /**
+     * Check to see if the given directory is a Sword mods.d directory
+     * and then add it to the list if it is.
+     */
+    private static void testDefaultPath(List bookDirs, File path)
+    {
+        if (path == null)
+        {
+            return;
+        }
+
+        File mods = new File(path, SwordConstants.DIR_CONF);
+        if (mods.isDirectory() && mods.canRead())
+        {
+            bookDirs.add(path);
+        }
+    }
+
+    /**
+     * Check to see if the given directory is a Sword mods.d directory
+     * and then add it to the list if it is.
+     * @param readonly 
+     */
+    private static void testDefaultPath(List bookDirs, String path)
+    {
+        if (path == null)
+        {
+            return;
+        }
+
+        testDefaultPath(bookDirs, new File(path));
+    }
+
+    private static File getDefaultDownloadPath()
+    {
+        File path = null;
+        File[] possiblePaths = getDefaultPaths();
+
+        if (possiblePaths != null)
+        {
+            for (int i = 0; i < possiblePaths.length; i++)
+            {
+                File mods = new File(possiblePaths[i], SwordConstants.DIR_CONF);
+                if (mods.canWrite())
+                {
+                    path = possiblePaths[i];
+                    break;
+                }
+            }
+        }
+
+        // If it is not found on the path then it doesn't exist yet and needs to be established
+        if (path == null)
+        {
+            URL userDataArea = Project.instance().getUserProjectDir(DIR_SWORD_CONF, DIR_SWORD_CONF_ALT);
+            path = new File(userDataArea.getFile());
+        }
+
+        return path;
+    }
+
+    private static void migrateBookDir()
+    {
+        // Books should be on this path
+        URL userDataArea = Project.instance().getUserProjectDir(DIR_SWORD_CONF, DIR_SWORD_CONF_ALT);
+
+        File swordBookPath = new File(userDataArea.getFile());
+
+        // The "old" Book location might be in one of two locations
+        // It might be ~/.jsword or the new project dir
+        File oldPath = new File(Project.instance().getDeprecatedUserProjectDir().getFile());
+
+        if (oldPath.isDirectory())
+        {
+            migrateBookDir(oldPath, swordBookPath);
+            return;
+        }
+
+        oldPath = new File(Project.instance().getUserProjectDir().getFile());
+
+        if (oldPath.isDirectory())
+        {
+            migrateBookDir(oldPath, swordBookPath);
+        }
+    }
+
+    private static void migrateBookDir(File oldPath, File newPath)
+    {
+        // move the modules and confs
+        File oldDataDir = new File(oldPath, SwordConstants.DIR_DATA);
+        File newDataDir = new File(newPath, SwordConstants.DIR_DATA);
+        File oldConfDir = new File(oldPath, SwordConstants.DIR_CONF);
+        File newConfDir = new File(newPath, SwordConstants.DIR_CONF);
+
+        // move the modules
+        if (!migrate(oldDataDir, newDataDir))
+        {
+            return;
+        }
+
+        // move the confs
+        if (!migrate(oldConfDir, newConfDir))
+        {
+            // oops, restore the modules
+            migrate(newDataDir, oldDataDir);
+        }
+    }
+
+    private static boolean migrate(File oldPath, File newPath)
+    {
+        if (oldPath.equals(newPath) || !oldPath.exists())
+        {
+            return true;
+        }
+
+        File parent = newPath.getParentFile();
+        if (!parent.exists())
+        {
+            parent.mkdirs();
+        }
+
+        return oldPath.renameTo(newPath);
+    }
+
+    /**
+     * @return Returns the download directory.
+     */
+    public static File getDownloadDir()
+    {
+        return downloadDir;
+    }
+
+    /**
+     * @param downloadDir The download directory to set.
+     */
+    public static void setDownloadDir(File dlDir)
+    {
+        if (!dlDir.getPath().equals("")) //$NON-NLS-1$
+        {
+            downloadDir = dlDir;
+            log.debug("Setting sword download directory to: " + dlDir); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Check that the directories in the version directory really
+     * represent versions.
+     */
+    static class CustomFilenameFilter implements FilenameFilter
+    {
+        /* (non-Javadoc)
+         * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
+         */
+        public boolean accept(File parent, String name)
+        {
+            return !name.startsWith(PREFIX_GLOBALS) && name.endsWith(SwordConstants.EXTENSION_CONF);
+        }
+    }
+
+    /**
+     * Default windows installation directory
+     */
+    private static final String DIR_WINDOWS_DEFAULT = "C:\\Program Files\\CrossWire\\The SWORD Project"; //$NON-NLS-1$
+
+    /**
+     * Library may be a sibling of DIR_WINDOWS_DEFAULT or SWORD_HOME or CWD
+     */
+    private static final String DIR_SWORD_LIBRARY = "library"; //$NON-NLS-1$
+
+    /**
+     * Users config directory for Sword in Unix
+     */
+    private static final String DIR_SWORD_CONF = ".sword"; //$NON-NLS-1$
+
+    /**
+     * Users config directory for Sword in Unix
+     */
+    private static final String DIR_SWORD_CONF_ALT = "Sword"; //$NON-NLS-1$
+
+    /**
+     * Sword global config file
+     */
+    private static final String SWORD_GLOBAL_CONF = "sword.conf"; //$NON-NLS-1$
+
+    /**
+     * Sword global config file locations
+     */
+    private static final String DIR_SWORD_GLOBAL_CONF = "/etc:/usr/local/etc"; //$NON-NLS-1$
+
+    /**
+     * Sword global config file's path to where mods can be found
+     */
+    private static final String DATA_PATH = "DataPath"; //$NON-NLS-1$
+
+    /**
+     * Sword global config file's path to where mods can be found
+     */
+    private static final String AUGMENT_PATH = "AugmentPath"; //$NON-NLS-1$
+
+    /**
+     * System property for sword home directory
+     */
+    private static final String PROPERTY_SWORD_HOME = "sword.home"; //$NON-NLS-1$
+
+    /**
+     * Java system property for users home directory
+     */
+    private static final String PROPERTY_USER_HOME = "user.home"; //$NON-NLS-1$
+
+    /**
+     * File prefix for config file
+     */
+    private static final String PREFIX_GLOBALS = "globals."; //$NON-NLS-1$
+
+    /**
+     * The directory URL
+     */
+    private static File[] augmentPath = new File[0];
+
+    /**
+     * The directory URL
+     */
+    private static File downloadDir = getDefaultDownloadPath();
+
+    /**
+     * The log stream
+     */
+    private static final Logger log = Logger.getLogger(SwordBookPath.class);
+
+}

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordUtil.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordUtil.java	2006-08-25 17:30:52 UTC (rev 1119)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordUtil.java	2006-08-26 17:35:11 UTC (rev 1120)
@@ -245,5 +245,5 @@
     /**
      * The size to read/write when unzipping a compressed byte array of unknown size.
      */
-    final static int ZBUF_SIZE = 2048;
+    private static final int ZBUF_SIZE = 2048;
 }

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/util/Project.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/util/Project.java	2006-08-25 17:30:52 UTC (rev 1119)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/util/Project.java	2006-08-26 17:35:11 UTC (rev 1120)
@@ -37,7 +37,7 @@
  * on different operating systems. These are:<br/>
  * 
  * <table>
- * <tr><td>Mac OS X</td><td>~/Library/JSword</td></tr>
+ * <tr><td>Mac OS X</td><td>~/Library/Application Support/JSword</td></tr>
  * <tr><td>Win NT/2000/XP</td><td>%APPDATA%/JSword</td></tr>
  * <tr><td>Win 9x/ME with profiles enabled</td><td>%WINDIR%/profiles/Application Data/JSword</td></tr>
  * <tr><td>Win 9x/ME</td><td>%WINDIR%/Application Data/JSword</td></tr>
@@ -80,7 +80,7 @@
     /**
      * The Mac user settings parent directory
      */
-    public static final String MAC_USER_DATA_AREA = "Library"; //$NON-NLS-1$
+    public static final String MAC_USER_DATA_AREA = "Library/Application Support"; //$NON-NLS-1$
 
     /**
      * Accessor for the resource singleton.
@@ -99,16 +99,7 @@
      */
     private Project()
     {
-        try
-        {
-            establishUserProjectDir();
-            CWClassLoader.setHome(home);
-        }
-        catch (MalformedURLException ex)
-        {
-            log.fatal("Failed to create home directory URL", ex); //$NON-NLS-1$
-            assert false : ex;
-        }
+        CWClassLoader.setHome(getUserProjectDir());
 
         try
         {
@@ -128,53 +119,83 @@
      * Establishes the user's project directory.
      * @throws MalformedURLException
      */
-    private void establishUserProjectDir() throws MalformedURLException
+    public URL getUserProjectDir(String unixDefault, String winMacDefault)
     {
-        String user = System.getProperty("user.home"); //$NON-NLS-1$
-        String osName = System.getProperty("os.name"); //$NON-NLS-1$
+        String projectDir = winMacDefault;
+        URL path = null;
+        try
+        {
+            if (userArea == null)
+            {
+                String user = System.getProperty("user.home"); //$NON-NLS-1$
+                String osName = System.getProperty("os.name"); //$NON-NLS-1$
 
-        URL path = new URL(NetUtil.PROTOCOL_FILE, null, user);
-        
-        String projectDir = DIR_PROJECT_ALT;
-    
-        if (osName.startsWith("Mac OS X")) //$NON-NLS-1$
-        {
-            path = NetUtil.lengthenURL(path, MAC_USER_DATA_AREA);
+                path = new URL(NetUtil.PROTOCOL_FILE, null, user);
+
+                if (osName.startsWith("Mac OS X")) //$NON-NLS-1$
+                {
+                    path = NetUtil.lengthenURL(path, MAC_USER_DATA_AREA);
+                }
+                else if (osName.startsWith("Windows")) //$NON-NLS-1$
+                {
+                    path = NetUtil.lengthenURL(path, WIN32_USER_DATA_AREA);
+                }
+                else
+                {
+                    projectDir = unixDefault;
+                }
+                userArea = path;
+            }
+            path = NetUtil.lengthenURL(userArea, projectDir);
         }
-        else if (osName.startsWith("Windows")) //$NON-NLS-1$
+        catch (MalformedURLException ex)
         {
-            path = NetUtil.lengthenURL(path, WIN32_USER_DATA_AREA);
+            log.fatal("Failed to find user's private data area", ex); //$NON-NLS-1$
+            assert false : ex;
         }
-        else
-        {
-            projectDir = DIR_PROJECT;
-        }
 
-        path = NetUtil.lengthenURL(path, projectDir);
+        return path;
+    }
 
-        URL oldPath = getDeprecatedUserProjectDir();
-        if (!migrateUserProjectDir(oldPath, path))
+    /**
+     * Establishes the user's project directory.
+     * @throws MalformedURLException
+     */
+    public URL getUserProjectDir()
+    {
+        if (home == null)
         {
-            path = oldPath;
+            URL path = getUserProjectDir(DIR_PROJECT, DIR_PROJECT_ALT);
+            URL oldPath = getDeprecatedUserProjectDir();
+            home = migrateUserProjectDir(oldPath, path);
         }
 
-        home = path;
+        return home;
     }
 
     /**
      * Get the location where the project dir used to be.
+     * 
      * @return ~/.jsword
      * @throws MalformedURLException
      */
-    private URL getDeprecatedUserProjectDir() throws MalformedURLException
+    public URL getDeprecatedUserProjectDir()
     {
-        String user = System.getProperty("user.home"); //$NON-NLS-1$
+        try
+        {
+            String user = System.getProperty("user.home"); //$NON-NLS-1$
 
-        URL path = new URL(NetUtil.PROTOCOL_FILE, null, user);
-        
-        path = NetUtil.lengthenURL(path, DIR_PROJECT);
+            URL path = new URL(NetUtil.PROTOCOL_FILE, null, user);
+            path = NetUtil.lengthenURL(path, DIR_PROJECT);
 
-        return path;
+            return path;
+        }
+        catch (MalformedURLException ex)
+        {
+            log.fatal("Failed to create home directory URL", ex); //$NON-NLS-1$
+            assert false : ex;
+        }
+        return null;
     }
 
     /**
@@ -182,26 +203,26 @@
      * 
      * @param oldPath the path to the old, deprecated location
      * @param newPath the path to the new location
-     * @return true if the migration was possible or not needed.
+     * @return newPath if the migration was possible or not needed.
      */
-    private boolean migrateUserProjectDir(URL oldPath, URL newPath)
+    private URL migrateUserProjectDir(URL oldPath, URL newPath)
     {
-        boolean result = true;
-        try
+        if (oldPath.equals(newPath))
         {
-            if (!oldPath.equals(newPath) && NetUtil.isDirectory(oldPath))
+            return newPath;
+        }
+
+        if (NetUtil.isDirectory(oldPath))
+        {
+            File oldDir = new File(oldPath.getFile());
+            File newDir = new File(newPath.getFile());
+            if (oldDir.renameTo(newDir))
             {
-                File oldDir = NetUtil.getAsFile(oldPath);
-                File newDir = NetUtil.getAsFile(newPath);
-                result = oldDir.renameTo(newDir);
+                return newPath;
             }
+            return oldPath;
         }
-        catch (IOException e)
-        {
-            log.warn("Failed to move user's project directory", e); //$NON-NLS-1$
-            result = false;
-        }
-        return result;
+        return newPath;
     }
 
     /**
@@ -216,7 +237,7 @@
      */
     public URL getWritablePropertiesURL(String subject)
     {
-        return NetUtil.lengthenURL(home, subject + FileUtil.EXTENSION_PROPERTIES);
+        return NetUtil.lengthenURL(getUserProjectDir(), subject + FileUtil.EXTENSION_PROPERTIES);
     }
 
     /**
@@ -238,7 +259,7 @@
      */
     public URL getTempScratchSpace(String subject, boolean create) throws IOException
     {
-        URL temp = NetUtil.lengthenURL(home, subject);
+        URL temp = NetUtil.lengthenURL(getUserProjectDir(), subject);
 
         if (create && !NetUtil.isDirectory(temp))
         {
@@ -249,6 +270,11 @@
     }
 
     /**
+     * The parent directory for the home of this application
+     */
+    private URL userArea;
+
+    /**
      * The home for this application
      */
     private URL home;




More information about the jsword-svn mailing list