1
22 package org.crosswire.jsword.book.sword;
23
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FilenameFilter;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.net.URI;
30 import java.util.ArrayList;
31 import java.util.List;
32
33 import org.crosswire.common.util.CWProject;
34 import org.crosswire.common.util.Logger;
35 import org.crosswire.common.util.OSType;
36 import org.crosswire.common.util.PropertyMap;
37 import org.crosswire.common.util.StringUtil;
38 import org.crosswire.jsword.book.BookException;
39 import org.crosswire.jsword.book.Books;
40
41
49 public class SwordBookPath {
50
53 private SwordBookPath() {
54 }
55
56
63 public static void setAugmentPath(File[] theNewDirs) throws BookException {
64 File[] newDirs = theNewDirs;
65 if (newDirs == null) {
66 return;
67 }
68
69 SwordBookPath.augmentPath = newDirs.clone();
70
71 Books.installed().registerDriver(SwordBookDriver.instance());
73 }
74
75
80 public static File[] getAugmentPath() {
81 return augmentPath.clone();
82 }
83
84
91 public static File[] getSwordPath() {
92 ArrayList<File> swordPath = new ArrayList<File>();
93
94 swordPath.add(getSwordDownloadDir());
96
97 if (augmentPath != null) {
99 for (int i = 0; i < augmentPath.length; i++) {
100 File path = augmentPath[i];
101 if (!swordPath.contains(path)) {
102 swordPath.add(path);
103 }
104 }
105 }
106
107 File[] defaultPath = getDefaultPaths();
108 if (defaultPath != null) {
110 for (int i = 0; i < defaultPath.length; i++) {
111 File path = defaultPath[i];
112 if (!swordPath.contains(path)) {
113 swordPath.add(path);
114 }
115 }
116 }
117
118 return swordPath.toArray(new File[swordPath.size()]);
119 }
120
121
128 public static String[] getBookList(File bookDir) {
129 return bookDir.list(new CustomFilenameFilter());
130 }
131
132
136 private static File[] getDefaultPaths() {
137 migrateBookDir();
139
140 List<File> bookDirs = new ArrayList<File>();
141
142 String home = System.getProperty(PROPERTY_USER_HOME);
143
144 readSwordConf(bookDirs, ".");
146
147 testDefaultPath(bookDirs, ".");
149
150 testDefaultPath(bookDirs, ".." + File.separator + DIR_SWORD_LIBRARY);
152
153 String swordhome = System.getProperty(PROPERTY_SWORD_HOME);
157 if (swordhome != null) {
158 testDefaultPath(bookDirs, swordhome);
159
160 testDefaultPath(bookDirs, swordhome + File.separator + ".." + File.separator + DIR_SWORD_LIBRARY);
162 }
163
164 if (System.getProperty("os.name").startsWith("Windows")) {
165 testDefaultPath(bookDirs, DIR_WINDOWS_DEFAULT);
166 testDefaultPath(bookDirs, DIR_WINDOWS_DEFAULT + File.separator + ".." + File.separator + DIR_SWORD_LIBRARY);
168 }
169
170 readSwordConf(bookDirs, home + File.separator + DIR_SWORD_CONF);
172
173 String[] sysconfigPaths = StringUtil.split(DIR_SWORD_GLOBAL_CONF, ':');
175 for (int i = 0; i < sysconfigPaths.length; i++) {
176 readSwordConf(bookDirs, sysconfigPaths[i]);
177 }
178
179 URI userDataArea = OSType.getOSType().getUserAreaFolder(DIR_SWORD_CONF, DIR_SWORD_CONF_ALT);
180
181 testDefaultPath(bookDirs, new File(userDataArea.getPath()));
183
184 testDefaultPath(bookDirs, new File(CWProject.instance().getWritableProjectDir().getPath()));
189
190 return bookDirs.toArray(new File[bookDirs.size()]);
191 }
192
193 private static void readSwordConf(List<File> bookDirs, File swordConfDir) {
194 File sysconfig = new File(swordConfDir, SWORD_GLOBAL_CONF);
195 if (sysconfig.canRead()) {
196 InputStream is = null;
197 try {
198 PropertyMap prop = new PropertyMap();
199 is = new FileInputStream(sysconfig);
200 prop.load(is);
201 String datapath = prop.get(DATA_PATH);
202 testDefaultPath(bookDirs, datapath);
203 datapath = prop.get(AUGMENT_PATH);
204 testDefaultPath(bookDirs, datapath);
205 } catch (IOException ex) {
206 log.warn("Failed to read system config file", ex);
207 } finally {
208 if (is != null) {
209 try {
210 is.close();
211 } catch (IOException e) {
212 log.warn("Failed to close system config file", e);
213 }
214 }
215 }
216 }
217 }
218
219 private static void readSwordConf(List<File> bookDirs, String swordConfDir) {
220 readSwordConf(bookDirs, new File(swordConfDir));
221 }
222
223
232 private static void testDefaultPath(List<File> bookDirs, File path) {
233 if (path == null) {
234 return;
235 }
236
237 File mods = new File(path, SwordConstants.DIR_CONF);
238 if (mods.isDirectory() && mods.canRead()) {
239 bookDirs.add(path);
240 }
241 }
242
243
252 private static void testDefaultPath(List<File> bookDirs, String path) {
253 if (path == null) {
254 return;
255 }
256
257 testDefaultPath(bookDirs, new File(path));
258 }
259
260 private static File getDefaultDownloadPath() {
261 File path = null;
262 File[] possiblePaths = getDefaultPaths();
263
264 if (possiblePaths != null) {
265 for (int i = 0; i < possiblePaths.length; i++) {
266 File mods = new File(possiblePaths[i], SwordConstants.DIR_CONF);
267 if (mods.canWrite()) {
268 path = possiblePaths[i];
269 break;
270 }
271 }
272 }
273
274 if (path == null) {
277 URI userDataArea = OSType.getOSType().getUserAreaFolder(DIR_SWORD_CONF, DIR_SWORD_CONF_ALT);
278 path = new File(userDataArea.getPath());
279 }
280
281 return path;
282 }
283
284 private static void migrateBookDir() {
285 URI userDataArea = OSType.getOSType().getUserAreaFolder(DIR_SWORD_CONF, DIR_SWORD_CONF_ALT);
287
288 File swordBookPath = new File(userDataArea.getPath());
289
290 File oldPath = new File(CWProject.instance().getDeprecatedWritableProjectDir().getPath());
293
294 if (oldPath.isDirectory()) {
295 migrateBookDir(oldPath, swordBookPath);
296 return;
297 }
298
299 oldPath = new File(CWProject.instance().getWritableProjectDir().getPath());
301
302 if (oldPath.isDirectory()) {
303 migrateBookDir(oldPath, swordBookPath);
304 return;
305 }
306
307 oldPath = new File(OSType.DEFAULT.getUserAreaFolder(DIR_SWORD_CONF, DIR_SWORD_CONF_ALT).getPath());
309 if (oldPath.isDirectory()) {
310 migrateBookDir(oldPath, swordBookPath);
311 }
312 }
313
314 private static void migrateBookDir(File oldPath, File newPath) {
315 File oldDataDir = new File(oldPath, SwordConstants.DIR_DATA);
317 File newDataDir = new File(newPath, SwordConstants.DIR_DATA);
318 File oldConfDir = new File(oldPath, SwordConstants.DIR_CONF);
319 File newConfDir = new File(newPath, SwordConstants.DIR_CONF);
320
321 if (!migrate(oldDataDir, newDataDir)) {
323 return;
324 }
325
326 if (!migrate(oldConfDir, newConfDir)) {
328 migrate(newDataDir, oldDataDir);
330 }
331 }
332
333 private static boolean migrate(File oldPath, File newPath) {
334 if (oldPath.equals(newPath) || !oldPath.exists()) {
335 return true;
336 }
337
338 File parent = newPath.getParentFile();
340 if (!parent.exists() && !parent.mkdirs()) {
341 return false;
342 }
343
344 return oldPath.renameTo(newPath);
345 }
346
347
353 public static File getSwordDownloadDir() {
354 if (overrideDownloadDir != null) {
355 return overrideDownloadDir;
356 }
357 return defaultDownloadDir;
358 }
359
360
363 public static File getDownloadDir() {
364 return overrideDownloadDir;
365 }
366
367
371 public static void setDownloadDir(File dlDir) {
372 if (!"".equals(dlDir.getPath())) {
373 overrideDownloadDir = dlDir;
374 log.debug("Setting sword download directory to: " + dlDir);
375 }
376 }
377
378
382 static class CustomFilenameFilter implements FilenameFilter {
383
388 public boolean accept(File parent, String name) {
389 return !name.startsWith(PREFIX_GLOBALS) && name.endsWith(SwordConstants.EXTENSION_CONF);
390 }
391 }
392
393
396 private static final String DIR_WINDOWS_DEFAULT = "C:\\Program Files\\CrossWire\\The SWORD Project";
397
398
401 private static final String DIR_SWORD_LIBRARY = "library";
402
403
406 private static final String DIR_SWORD_CONF = ".sword";
407
408
411 private static final String DIR_SWORD_CONF_ALT = "Sword";
412
413
416 private static final String SWORD_GLOBAL_CONF = "sword.conf";
417
418
421 private static final String DIR_SWORD_GLOBAL_CONF = "/etc:/usr/local/etc";
422
423
426 private static final String DATA_PATH = "DataPath";
427
428
431 private static final String AUGMENT_PATH = "AugmentPath";
432
433
436 private static final String PROPERTY_SWORD_HOME = "sword.home";
437
438
441 private static final String PROPERTY_USER_HOME = "user.home";
442
443
446 private static final String PREFIX_GLOBALS = "globals.";
447
448
451 private static File[] augmentPath = new File[0];
452
453
456 private static File defaultDownloadDir = getDefaultDownloadPath();
457
458
461 private static File overrideDownloadDir;
462
463
466 private static final Logger log = Logger.getLogger(SwordBookPath.class);
467
468 }
469