/** * 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: 2008 * The copyright to this program is held by it's authors. * * ID: $Id: BookIndexer.java 1466 2007-07-02 02:48:09Z dmsmith $ */ package net.bible.service.download; import net.bible.android.activity.R; import net.bible.android.view.activity.base.Dialogs; import net.bible.service.common.Logger; import org.crosswire.common.util.Filter; import org.crosswire.jsword.book.Book; import org.crosswire.jsword.book.BookException; import org.crosswire.jsword.book.BookFilter; import org.crosswire.jsword.book.Books; import org.crosswire.jsword.book.install.InstallException; import org.crosswire.jsword.book.install.InstallManager; import org.crosswire.jsword.book.install.Installer; import org.crosswire.jsword.book.sword.SwordBookMetaData; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; /** * Originally copied from BookInstaller it calls Sword routines related to installation and removal of books and indexes * * @see gnu.lgpl.License for license details.<br> * The copyright to this program is held by it's authors. * @author DM Smith [dmsmith555 at yahoo dot com] * @author Martin Denham [mjdenham at gmail dot com] */ public class DownloadManager { public static final String REPOSITORY_KEY = "repository"; private InstallManager installManager; private static final Logger log = new Logger(DownloadManager.class.getName()); public DownloadManager() { installManager = new InstallManager(); } /** * @param filter * @return */ public List<Book> getDownloadableBooks(BookFilter filter, String repo, boolean refresh) throws InstallException { List<Book> documents = new ArrayList<>(); Installer installer = null; try { // If we know the name of the installer we can get it directly installer = installManager.getInstaller(repo); if (installer==null) { log.error("Error getting installer for repo "+repo); Dialogs.getInstance().showErrorMsg(R.string.error_occurred, new Exception("Error getting installer for repo "+repo)); documents = Collections.emptyList(); } else { // Now we can get the list of books log.debug("getting downloadable books"); if (refresh || installer.getBooks().size()==0) { //todo should warn user of implications of downloading book list e.g. from persecuted country log.warn("Reloading book list"); installer.reloadBookList(); } // Get a list of all the available books documents = installer.getBooks(filter); //$NON-NLS-1$ } } catch (Exception e) { // ignore error because some minor repos are unreliable log.error("Fatal error downloading books from "+repo, e); } catch (OutOfMemoryError oom) { // eBible repo throws OOM errors on smaller devices log.error("Out of memory error downloading books from "+repo); } finally { //free memory if (installer!=null) { installer.close(); } System.gc(); } log.info("number of documents available:"+documents.size()); return documents; } /** * Install a book, overwriting it if the book to be installed is newer. * * @param repositoryName * the name of the repository from which to get the book * @param book * the book to get * @throws BookException * @throws InstallException */ public void installBook(final String repositoryName, final Book book) throws BookException, InstallException { // Delete the book, if present // At the moment, JSword will not re-install. Later it will, if the // remote version is greater. String bookInitials = book.getInitials(); Book installedBook = Books.installed().getBook(bookInitials); if (installedBook!= null) { // installedBook may differ by case of initials if Xiphos so delete installedBook rather than book unregisterBook(installedBook); } try { // An installer knows how to install books Installer installer = installManager.getInstaller(repositoryName); installer.install(book); // reload metadata to ensure the correct location is set, otherwise maps won't show ((SwordBookMetaData)book.getBookMetaData()).reload(new Filter() { @Override public boolean test(Object obj) { return true; } }); } catch (InstallException ex) { Dialogs.getInstance().showErrorMsg(R.string.error_occurred, ex); } } /** * Install a book's index, overwriting it if it exists * * @param repositoryName * the name of the repository from which to get the index * @param book * the book to get the index for * @throws BookException * @throws InstallException */ public void installIndexInNewThread(String repositoryName, Book book) throws BookException, InstallException { // An installer knows how to install indexes log.debug("Install index in new thread"); Installer installer = installManager.getInstaller(repositoryName); IndexDownloader idt = new IndexDownloader(); idt.downloadIndexInNewThread(installer, book); } /** * Install a book's index, overwriting it if it exists * * @param repositoryName * the name of the repository from which to get the index * @param book * the book to get the index for * @throws BookException * @throws InstallException */ public void installIndex(String repositoryName, Book book) throws BookException, InstallException { // An installer knows how to install indexes log.debug("Install index for "+book.getInitials()); Installer installer = installManager.getInstaller(repositoryName); IndexDownloader idt = new IndexDownloader(); idt.downloadIndex(installer, book); } /** * Unregister a book from Sword registry. * * This used to delete the book but there is an mysterious bug in deletion (see below). * * @param book * the book to delete * @throws BookException */ private void unregisterBook(Book book) throws BookException { // this just seems to work so leave it here // I used to think that the next delete was better - what a mess // see this for potential problem: http://stackoverflow.com/questions/20437626/file-exists-returns-false-for-existing-file-in-android // does file.exists return an incorrect value? // To see the problem, reverse the commented lines below, and try downloading 2 or more Bibles that are already installed Books.installed().removeBook(book); // Avoid deleting all dir and files because "Java is known not to delete files immediately, so mkdir may fail sometimes" // http://stackoverflow.com/questions/617414/create-a-temporary-directory-in-java // // Actually do the delete // This should be a call on installer. //book.getDriver().delete(book); } /** * Get a list of all known installers. * * @return the list of installers */ public Map<String, Installer> getInstallers() { // Ask the Install Manager for a map of all known remote repositories // sites return installManager.getInstallers(); } /** * Get a list of books in a repository by BookFilter. * * @param filter * The book filter * @see BookFilter * @see Books */ public List<Book> getRepositoryBooks(String repositoryName, BookFilter filter) { return installManager.getInstaller(repositoryName).getBooks(filter); } /** * Reload the local cache for a remote repository. * * @param repositoryName * @throws InstallException */ public void reloadBookList(String repositoryName) throws InstallException { installManager.getInstaller(repositoryName).reloadBookList(); } /** * Get a Book from the repository. Note this does not install it. * * @param repositoryName * the repository from which to get the book * @param bookInitials * the name of the book to get * @return the Book */ public Book getRepositoryBook(String repositoryName, String bookInitials) { return installManager.getInstaller(repositoryName).getBook(bookInitials); } }