1   /**
2    * Distribution License:
3    * JSword is free software; you can redistribute it and/or modify it under
4    * the terms of the GNU Lesser General Public License, version 2.1 or later
5    * as published by the Free Software Foundation. This program is distributed
6    * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
7    * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8    * See the GNU Lesser General Public License for more details.
9    *
10   * The License is available on the internet at:
11   *      http://www.gnu.org/copyleft/lgpl.html
12   * or by writing to:
13   *      Free Software Foundation, Inc.
14   *      59 Temple Place - Suite 330
15   *      Boston, MA 02111-1307, USA
16   *
17   * © CrossWire Bible Society, 2008 - 2016
18   *
19   */
20  package org.crosswire.jsword.bridge;
21  
22  import java.util.List;
23  import java.util.Map;
24  
25  import org.crosswire.jsword.book.Book;
26  import org.crosswire.jsword.book.BookException;
27  import org.crosswire.jsword.book.BookFilter;
28  import org.crosswire.jsword.book.BookFilters;
29  import org.crosswire.jsword.book.Books;
30  import org.crosswire.jsword.book.install.InstallException;
31  import org.crosswire.jsword.book.install.InstallManager;
32  import org.crosswire.jsword.book.install.Installer;
33  
34  /**
35   * Exports the Book in SWORD's imp format. This is identical to SWORD's mod2imp.
36   * Note: it does not work with GenBook.
37   * 
38   * @see gnu.lgpl.License The GNU Lesser General Public License for details.
39   * @author DM Smith
40   */
41  public class BookInstaller {
42  
43      public BookInstaller() {
44          installManager = new InstallManager();
45      }
46  
47      /**
48       * Uninstall a book.
49       * 
50       * @param book
51       *            the book to delete
52       * @throws BookException
53       */
54      public void deleteBook(Book book) throws BookException {
55          // Actually do the delete
56          // This should be a call on installer.
57          // This will also remove the book from the list of installed books.
58          book.getDriver().delete(book);
59      }
60  
61      /**
62       * Get a list of all known installers.
63       * 
64       * @return the list of installers
65       */
66      public Map<String, Installer> getInstallers() {
67          // Ask the Install Manager for a map of all known remote repositories
68          // sites
69          return installManager.getInstallers();
70      }
71  
72      /**
73       * Get a list of all installed books.
74       * 
75       * @return the list of installed books
76       */
77      public static List<Book> getInstalledBooks() {
78          return Books.installed().getBooks();
79      }
80  
81      /**
82       * Get a list of installed books by BookFilter.
83       * 
84       * @param filter
85       *            The book filter
86       * @return the list of matching books
87       * @see BookFilter
88       * @see Books
89       */
90      public static List<Book> getInstalledBooks(BookFilter filter) {
91          return Books.installed().getBooks(filter);
92      }
93  
94      /**
95       * Get a list of books by CustomFilter specification
96       * 
97       * @param filterSpec
98       *            The filter string
99       * @return the list of matching books
100      * @see BookFilters#getCustom(java.lang.String)
101      * @see Books
102      */
103     public static List<Book> getInstalledBooks(String filterSpec) {
104         return getInstalledBooks(BookFilters.getCustom(filterSpec));
105     }
106 
107     /**
108      * Get a particular installed book by initials.
109      * 
110      * @param bookInitials
111      *            The book name to search for
112      * @return The found book. Null otherwise.
113      */
114     public static Book getInstalledBook(String bookInitials) {
115         return Books.installed().getBook(bookInitials);
116     }
117 
118     /**
119      * Get a list of all known books for an installer.
120      * 
121      * @param repositoryName
122      * @return the list of books at that repository
123      */
124     public List<Book> getRepositoryBooks(String repositoryName) {
125         return installManager.getInstaller(repositoryName).getBooks();
126     }
127 
128     /**
129      * Get a list of books in a repository by BookFilter.
130      * 
131      * @param repositoryName 
132      *            The name of the repository
133      * @param filter
134      *            The book filter
135      * @return the matching books
136      * @see BookFilter
137      * @see Books
138      */
139     public List<Book> getRepositoryBooks(String repositoryName, BookFilter filter) {
140         return installManager.getInstaller(repositoryName).getBooks(filter);
141     }
142 
143     /**
144      * Get a list of books in a repository by CustomFilter specification
145      * 
146      * @param repositoryName 
147      *            the name of the repository
148      * @param filterSpec
149      *            The filter string
150      * @return the list of books
151      * @see BookFilters#getCustom(java.lang.String)
152      * @see Books
153      */
154     public List<Book> getRepositoryBooks(String repositoryName, String filterSpec) {
155         return getRepositoryBooks(repositoryName, BookFilters.getCustom(filterSpec));
156     }
157 
158     /**
159      * Get a particular installed book by initials.
160      * 
161      * @param repositoryName 
162      *            the name of the repository
163      * @param bookInitials
164      *            The book name to search for
165      * @return The found book. Null otherwise.
166      */
167     public Book getRepositoryBook(String repositoryName, String bookInitials) {
168         return installManager.getInstaller(repositoryName).getBook(bookInitials);
169     }
170 
171     /**
172      * Reload the local cache for a remote repository.
173      * 
174      * @param repositoryName
175      * @throws InstallException
176      */
177     public void reloadBookList(String repositoryName) throws InstallException {
178         installManager.getInstaller(repositoryName).reloadBookList();
179     }
180 
181     /**
182      * Get a Book from the repository. Note this does not install it.
183      * 
184      * @param repositoryName
185      *            the repository from which to get the book
186      * @param bookName
187      *            the name of the book to get
188      * @return the Book
189      */
190     public Book getBook(String repositoryName, String bookName) {
191         return installManager.getInstaller(repositoryName).getBook(bookName);
192     }
193 
194     /**
195      * Install a book, overwriting it if the book to be installed is newer.
196      * 
197      * @param repositoryName
198      *            the name of the repository from which to get the book
199      * @param book
200      *            the book to get
201      * @throws BookException
202      * @throws InstallException
203      */
204     public void installBook(String repositoryName, Book book) throws BookException, InstallException {
205         // An installer knows how to install books
206         Installer installer = installManager.getInstaller(repositoryName);
207 
208         // Delete the book, if present
209         // At the moment, JSword will not re-install. Later it will, if the
210         // remote version is greater.
211         if (Books.installed().getBook(book.getInitials()) != null) {
212             deleteBook(book);
213         }
214 
215         // Now install it. Note this is a background task.
216         installer.install(book);
217     }
218 
219     private InstallManager installManager;
220 
221     /**
222      * BookInstaller can manage the installation of books with the following
223      * capabilities.
224      * 
225      * <p>Usage: BookInstaller [option]</p>
226      * <table border="0">
227      * <caption>Options</caption>
228      * <tr>
229      * <td>uninstall</td>
230      * <td>bookName</td>
231      * <td>Uninstall book</td>
232      * </tr>
233      * <tr>
234      * <td>sources</td>
235      * <td>&nbsp;</td>
236      * <td>List source repositories</td>
237      * </tr>
238      * <tr>
239      * <td>list</td>
240      * <td>&nbsp;</td>
241      * <td>List installed books</td>
242      * </tr>
243      * <tr>
244      * <td>list</td>
245      * <td>repositoryName</td>
246      * <td>list available books from a repository</td>
247      * </tr>
248      * <tr>
249      * <td>reload</td>
250      * <td>repositoryName</td>
251      * <td>Reload the local cache for a repository</td>
252      * </tr>
253      * <tr>
254      * <td>install</td>
255      * <td>repositoryName bookName</td>
256      * <td>Install a book from a repository</td>
257      * </tr>
258      * </table>
259      * 
260      * @param args
261      */
262     public static void main(String[] args) {
263         if (args.length < 1) {
264             usage();
265             return;
266         }
267 
268         System.err.print("BookInstaller");
269         for (int i = 0; i < args.length; i++) {
270             System.err.print(' ');
271             System.err.print(args[i]);
272         }
273         System.err.print('\n');
274 
275         BookInstaller installer = new BookInstaller();
276 
277         String operation = args[0];
278         if ("uninstall".equalsIgnoreCase(operation)) {
279             if (args.length == 2) {
280                 Book b = Books.installed().getBook(args[1]);
281                 if (b == null) {
282                     System.err.println("Book not found");
283                     return;
284                 }
285                 try {
286                     installer.deleteBook(b);
287                 } catch (BookException e) {
288                     e.printStackTrace();
289                 }
290             } else {
291                 usage();
292             }
293         } else if ("sources".equalsIgnoreCase(operation)) {
294             // Get all the installers one after the other
295             Map<String, Installer> installers = installer.getInstallers();
296             for (String name : installers.keySet()) {
297                 System.out.println(name);
298             }
299         } else if ("list".equalsIgnoreCase(operation)) {
300             if (args.length == 1) {
301                 for (Book book : BookInstaller.getInstalledBooks()) {
302                     System.out.println(book.getInitials());
303                 }
304             } else if (args.length == 2) {
305                 for (Book book : installer.getRepositoryBooks(args[1])) {
306                     System.out.println(book.getInitials());
307                 }
308             } else {
309                 usage();
310             }
311         } else if ("reload".equalsIgnoreCase(operation)) {
312             if (args.length == 2) {
313                 try {
314                     installer.reloadBookList(args[1]);
315                 } catch (InstallException e) {
316                     e.printStackTrace();
317                 }
318             } else {
319                 usage();
320             }
321         } else if ("install".equalsIgnoreCase(operation)) {
322             if (args.length == 3) {
323                 Book b = installer.getBook(args[1], args[2]);
324                 if (b == null) {
325                     System.err.println("Book not found");
326                     return;
327                 }
328                 try {
329                     installer.installBook(args[1], b);
330                 } catch (BookException e) {
331                     e.printStackTrace();
332                 } catch (InstallException e) {
333                     e.printStackTrace();
334                 }
335             } else {
336                 usage();
337             }
338         } else {
339             usage();
340         }
341     }
342 
343     public static void usage() {
344         System.err.println("usage: BookInstaller <option>");
345         System.err.println("Options:");
346         System.err.println("    uninstall bookName                 Uninstall book");
347         System.err.println("    sources                            List remote source repositories");
348         System.err.println("    list                               List installed books");
349         System.err.println("    list      repositoryName           List available books from a repository");
350         System.err.println("    reload    repositoryName           Reload local cache for a repository");
351         System.err.println("    install   repositoryName bookName  Install a book from a repository");
352     }
353 }
354