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, 2013 - 2016
18   *
19   */
20  package org.crosswire.jsword.book.sword.state;
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.io.RandomAccessFile;
25  import java.net.URI;
26  
27  import org.crosswire.common.util.FileUtil;
28  import org.crosswire.common.util.IOUtil;
29  import org.crosswire.common.util.Reporter;
30  import org.crosswire.jsword.JSMsg;
31  import org.crosswire.jsword.book.BookException;
32  import org.crosswire.jsword.book.BookMetaData;
33  import org.crosswire.jsword.book.sword.RawLDBackend;
34  import org.crosswire.jsword.book.sword.SwordConstants;
35  import org.crosswire.jsword.book.sword.SwordUtil;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  /**
40   * State for {@link RawLDBackend}
41   * 
42   * 
43   * @see gnu.lgpl.License The GNU Lesser General Public License for details.
44   * @author DM Smith
45   */
46  public class RawLDBackendState extends AbstractOpenFileState  {
47      /**
48       * This is default package access for forcing the use of the
49       * OpenFileStateManager to manage the creation. Not doing so may result in
50       * new instances of OpenFileState being created for no reason, and as a
51       * result, if they are released to the OpenFileStateManager by mistake this
52       * would result in leakage
53       * 
54       * @param bookMetaData the appropriate metadata for the book
55       */
56      RawLDBackendState(BookMetaData bookMetaData) throws BookException {
57          super(bookMetaData);
58          URI path = null;
59          try {
60              path = SwordUtil.getExpandedDataPath(bookMetaData);
61          } catch (BookException e) {
62              Reporter.informUser(this, e);
63              throw e;
64          }
65  
66          try {
67              idxFile = new File(path.getPath() + SwordConstants.EXTENSION_INDEX);
68              datFile = new File(path.getPath() + SwordConstants.EXTENSION_DATA);
69  
70              if (!idxFile.canRead()) {
71                  // TRANSLATOR: Common error condition: The file could not be
72                  // read. There can be many reasons.
73                  // {0} is a placeholder for the file.
74                  Reporter.informUser(this, new BookException(JSMsg.gettext("Error reading {0}", idxFile.getAbsolutePath())));
75  
76                  // As per previous behaviour, we continue with state half made, having informed the user of the error
77                  return;
78              }
79  
80              if (!datFile.canRead()) {
81                  // Throwing exception, as if we can't read our data file, then we might as well give up
82  
83                  // TRANSLATOR: Common error condition: The file could not be
84                  // read. There can be many reasons.
85                  // {0} is a placeholder for the file.
86                  BookException prob = new BookException(JSMsg.gettext("Error reading {0}", datFile.getAbsolutePath()));
87                  Reporter.informUser(this, prob);
88                  throw prob;
89              }
90  
91              // Open the files
92              idxRaf = new RandomAccessFile(idxFile, FileUtil.MODE_READ);
93              datRaf = new RandomAccessFile(datFile, FileUtil.MODE_READ);
94          } catch (IOException ex) {
95              //failed to open the files, so close them now
96              IOUtil.close(idxRaf);
97              IOUtil.close(datRaf);
98  
99              LOGGER.error("failed to open files", ex);
100             idxRaf = null;
101             datRaf = null;
102             // TRANSLATOR: Common error condition: The file could not be read.
103             // There can be many reasons.
104             // {0} is a placeholder for the file.
105             throw new BookException(JSMsg.gettext("Error reading {0}", datFile.getAbsolutePath()), ex);
106         }
107     }
108 
109     public void releaseResources() {
110         size = -1;
111         IOUtil.close(idxRaf);
112         IOUtil.close(datRaf);
113         idxRaf = null;
114         datRaf = null;
115     }
116 
117     /**
118      * @return the size
119      */
120     public int getSize() {
121         return size;
122     }
123 
124     /**
125      * @return the idxFile
126      */
127     public File getIdxFile() {
128         return idxFile;
129     }
130 
131     /**
132      * @return the idxRaf
133      */
134     public RandomAccessFile getIdxRaf() {
135         return idxRaf;
136     }
137 
138     /**
139      * @return the datRaf
140      */
141     public RandomAccessFile getDatRaf() {
142         return datRaf;
143     }
144 
145     /**
146      * @param size
147      *            the size to set
148      */
149     public void setSize(int size) {
150         this.size = size;
151     }
152 
153     /**
154      * The number of entries in the book.
155      */
156     private int size = -1;
157 
158     /**
159      * The index file
160      */
161     private File idxFile;
162 
163     /**
164      * The index random access file
165      */
166     private RandomAccessFile idxRaf;
167 
168     /**
169      * The data file
170      */
171     private File datFile;
172 
173     /**
174      * The data random access file
175      */
176     private RandomAccessFile datRaf;
177 
178     /**
179      * The log stream
180      */
181     private static final Logger LOGGER = LoggerFactory.getLogger(RawLDBackend.class);
182 }
183