1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
package org.crosswire.jsword.book.sword; |
21 | |
|
22 | |
import java.io.File; |
23 | |
import java.io.FileInputStream; |
24 | |
import java.io.FilenameFilter; |
25 | |
import java.io.IOException; |
26 | |
import java.io.InputStream; |
27 | |
import java.net.URI; |
28 | |
import java.util.ArrayList; |
29 | |
import java.util.List; |
30 | |
|
31 | |
import org.crosswire.common.util.CWProject; |
32 | |
import org.crosswire.common.util.OSType; |
33 | |
import org.crosswire.common.util.PropertyMap; |
34 | |
import org.crosswire.common.util.StringUtil; |
35 | |
import org.crosswire.jsword.book.BookException; |
36 | |
import org.crosswire.jsword.book.Books; |
37 | |
import org.slf4j.Logger; |
38 | |
import org.slf4j.LoggerFactory; |
39 | |
|
40 | |
|
41 | |
|
42 | |
|
43 | |
|
44 | |
|
45 | |
|
46 | |
|
47 | |
public final class SwordBookPath { |
48 | |
|
49 | |
|
50 | |
|
51 | 0 | private SwordBookPath() { |
52 | 0 | } |
53 | |
|
54 | |
|
55 | |
|
56 | |
|
57 | |
|
58 | |
|
59 | |
|
60 | |
|
61 | |
public static void setAugmentPath(File[] theNewDirs) throws BookException { |
62 | 0 | File[] newDirs = theNewDirs; |
63 | 0 | if (newDirs == null) { |
64 | 0 | return; |
65 | |
} |
66 | |
|
67 | 0 | SwordBookPath.augmentPath = newDirs.clone(); |
68 | |
|
69 | |
|
70 | 0 | Books.installed().registerDriver(SwordBookDriver.instance()); |
71 | 0 | } |
72 | |
|
73 | |
|
74 | |
|
75 | |
|
76 | |
|
77 | |
|
78 | |
public static File[] getAugmentPath() { |
79 | 0 | return augmentPath.clone(); |
80 | |
} |
81 | |
|
82 | |
|
83 | |
|
84 | |
|
85 | |
|
86 | |
|
87 | |
|
88 | |
|
89 | |
public static File[] getSwordPath() { |
90 | 0 | ArrayList<File> swordPath = new ArrayList<File>(); |
91 | |
|
92 | |
|
93 | 0 | swordPath.add(getSwordDownloadDir()); |
94 | |
|
95 | |
|
96 | 0 | if (augmentPath != null) { |
97 | 0 | for (int i = 0; i < augmentPath.length; i++) { |
98 | 0 | File path = augmentPath[i]; |
99 | 0 | if (!swordPath.contains(path)) { |
100 | 0 | swordPath.add(path); |
101 | |
} |
102 | |
} |
103 | |
} |
104 | |
|
105 | 0 | File[] defaultPath = getDefaultPaths(); |
106 | |
|
107 | 0 | if (defaultPath != null) { |
108 | 0 | for (int i = 0; i < defaultPath.length; i++) { |
109 | 0 | File path = defaultPath[i]; |
110 | 0 | if (!swordPath.contains(path)) { |
111 | 0 | swordPath.add(path); |
112 | |
} |
113 | |
} |
114 | |
} |
115 | |
|
116 | 0 | return swordPath.toArray(new File[swordPath.size()]); |
117 | |
} |
118 | |
|
119 | |
|
120 | |
|
121 | |
|
122 | |
|
123 | |
|
124 | |
|
125 | |
|
126 | |
public static String[] getBookList(File bookDir) { |
127 | 0 | return bookDir.list(new CustomFilenameFilter()); |
128 | |
} |
129 | |
|
130 | |
|
131 | |
|
132 | |
|
133 | |
|
134 | |
private static File[] getDefaultPaths() { |
135 | |
|
136 | 0 | migrateBookDir(); |
137 | |
|
138 | 0 | List<File> bookDirs = new ArrayList<File>(); |
139 | |
|
140 | 0 | String home = System.getProperty(PROPERTY_USER_HOME); |
141 | |
|
142 | |
|
143 | 0 | readSwordConf(bookDirs, "."); |
144 | |
|
145 | |
|
146 | 0 | testDefaultPath(bookDirs, "."); |
147 | |
|
148 | |
|
149 | 0 | testDefaultPath(bookDirs, ".." + File.separator + DIR_SWORD_LIBRARY); |
150 | |
|
151 | |
|
152 | |
|
153 | |
|
154 | 0 | String swordhome = System.getProperty(PROPERTY_SWORD_HOME); |
155 | 0 | if (swordhome != null) { |
156 | 0 | testDefaultPath(bookDirs, swordhome); |
157 | |
|
158 | |
|
159 | 0 | testDefaultPath(bookDirs, swordhome + File.separator + ".." + File.separator + DIR_SWORD_LIBRARY); |
160 | |
} |
161 | |
|
162 | 0 | if (System.getProperty("os.name").startsWith("Windows")) { |
163 | 0 | testDefaultPath(bookDirs, DIR_WINDOWS_DEFAULT); |
164 | |
|
165 | 0 | testDefaultPath(bookDirs, DIR_WINDOWS_DEFAULT + File.separator + ".." + File.separator + DIR_SWORD_LIBRARY); |
166 | |
} |
167 | |
|
168 | |
|
169 | 0 | readSwordConf(bookDirs, home + File.separator + DIR_SWORD_CONF); |
170 | |
|
171 | |
|
172 | 0 | String[] sysconfigPaths = StringUtil.split(DIR_SWORD_GLOBAL_CONF, ':'); |
173 | 0 | for (int i = 0; i < sysconfigPaths.length; i++) { |
174 | 0 | readSwordConf(bookDirs, sysconfigPaths[i]); |
175 | |
} |
176 | |
|
177 | 0 | URI userDataArea = OSType.getOSType().getUserAreaFolder(DIR_SWORD_CONF, DIR_SWORD_CONF_ALT); |
178 | |
|
179 | |
|
180 | 0 | testDefaultPath(bookDirs, new File(userDataArea.getPath())); |
181 | |
|
182 | |
|
183 | |
|
184 | |
|
185 | |
|
186 | 0 | testDefaultPath(bookDirs, new File(CWProject.instance().getWritableProjectDir().getPath())); |
187 | |
|
188 | 0 | return bookDirs.toArray(new File[bookDirs.size()]); |
189 | |
} |
190 | |
|
191 | |
private static void readSwordConf(List<File> bookDirs, File swordConfDir) { |
192 | 0 | File sysconfig = new File(swordConfDir, SWORD_GLOBAL_CONF); |
193 | 0 | if (sysconfig.canRead()) { |
194 | 0 | InputStream is = null; |
195 | |
try { |
196 | 0 | PropertyMap prop = new PropertyMap(); |
197 | 0 | is = new FileInputStream(sysconfig); |
198 | 0 | prop.load(is); |
199 | 0 | String datapath = prop.get(DATA_PATH); |
200 | 0 | testDefaultPath(bookDirs, datapath); |
201 | 0 | datapath = prop.get(AUGMENT_PATH); |
202 | 0 | testDefaultPath(bookDirs, datapath); |
203 | 0 | } catch (IOException ex) { |
204 | 0 | log.warn("Failed to read system config file", ex); |
205 | |
} finally { |
206 | 0 | if (is != null) { |
207 | |
try { |
208 | 0 | is.close(); |
209 | 0 | } catch (IOException e) { |
210 | 0 | log.warn("Failed to close system config file", e); |
211 | 0 | } |
212 | |
} |
213 | |
} |
214 | |
} |
215 | 0 | } |
216 | |
|
217 | |
private static void readSwordConf(List<File> bookDirs, String swordConfDir) { |
218 | 0 | readSwordConf(bookDirs, new File(swordConfDir)); |
219 | 0 | } |
220 | |
|
221 | |
|
222 | |
|
223 | |
|
224 | |
|
225 | |
|
226 | |
|
227 | |
|
228 | |
|
229 | |
|
230 | |
private static void testDefaultPath(List<File> bookDirs, File path) { |
231 | 0 | if (path == null) { |
232 | 0 | return; |
233 | |
} |
234 | |
|
235 | 0 | File mods = new File(path, SwordConstants.DIR_CONF); |
236 | 0 | if (mods.isDirectory() && mods.canRead()) { |
237 | 0 | bookDirs.add(path); |
238 | |
} |
239 | 0 | } |
240 | |
|
241 | |
|
242 | |
|
243 | |
|
244 | |
|
245 | |
|
246 | |
|
247 | |
|
248 | |
|
249 | |
|
250 | |
private static void testDefaultPath(List<File> bookDirs, String path) { |
251 | 0 | if (path == null) { |
252 | 0 | return; |
253 | |
} |
254 | |
|
255 | 0 | testDefaultPath(bookDirs, new File(path)); |
256 | 0 | } |
257 | |
|
258 | |
private static File getDefaultDownloadPath() { |
259 | 0 | File path = null; |
260 | 0 | File[] possiblePaths = getDefaultPaths(); |
261 | |
|
262 | 0 | if (possiblePaths != null) { |
263 | 0 | for (int i = 0; i < possiblePaths.length; i++) { |
264 | 0 | File mods = new File(possiblePaths[i], SwordConstants.DIR_CONF); |
265 | 0 | if (mods.canWrite()) { |
266 | 0 | path = possiblePaths[i]; |
267 | 0 | break; |
268 | |
} |
269 | |
} |
270 | |
} |
271 | |
|
272 | |
|
273 | |
|
274 | 0 | if (path == null) { |
275 | 0 | URI userDataArea = OSType.getOSType().getUserAreaFolder(DIR_SWORD_CONF, DIR_SWORD_CONF_ALT); |
276 | 0 | path = new File(userDataArea.getPath()); |
277 | |
} |
278 | |
|
279 | 0 | return path; |
280 | |
} |
281 | |
|
282 | |
private static void migrateBookDir() { |
283 | |
|
284 | 0 | URI userDataArea = OSType.getOSType().getUserAreaFolder(DIR_SWORD_CONF, DIR_SWORD_CONF_ALT); |
285 | |
|
286 | 0 | File swordBookPath = new File(userDataArea.getPath()); |
287 | |
|
288 | |
|
289 | |
|
290 | 0 | File oldPath = new File(CWProject.instance().getDeprecatedWritableProjectDir().getPath()); |
291 | |
|
292 | 0 | if (oldPath.isDirectory()) { |
293 | 0 | migrateBookDir(oldPath, swordBookPath); |
294 | 0 | return; |
295 | |
} |
296 | |
|
297 | |
|
298 | 0 | oldPath = new File(CWProject.instance().getWritableProjectDir().getPath()); |
299 | |
|
300 | 0 | if (oldPath.isDirectory()) { |
301 | 0 | migrateBookDir(oldPath, swordBookPath); |
302 | 0 | return; |
303 | |
} |
304 | |
|
305 | |
|
306 | 0 | oldPath = new File(OSType.DEFAULT.getUserAreaFolder(DIR_SWORD_CONF, DIR_SWORD_CONF_ALT).getPath()); |
307 | 0 | if (oldPath.isDirectory()) { |
308 | 0 | migrateBookDir(oldPath, swordBookPath); |
309 | |
} |
310 | 0 | } |
311 | |
|
312 | |
private static void migrateBookDir(File oldPath, File newPath) { |
313 | |
|
314 | 0 | File oldDataDir = new File(oldPath, SwordConstants.DIR_DATA); |
315 | 0 | File newDataDir = new File(newPath, SwordConstants.DIR_DATA); |
316 | 0 | File oldConfDir = new File(oldPath, SwordConstants.DIR_CONF); |
317 | 0 | File newConfDir = new File(newPath, SwordConstants.DIR_CONF); |
318 | |
|
319 | |
|
320 | 0 | if (!migrate(oldDataDir, newDataDir)) { |
321 | 0 | return; |
322 | |
} |
323 | |
|
324 | |
|
325 | 0 | if (!migrate(oldConfDir, newConfDir)) { |
326 | |
|
327 | 0 | migrate(newDataDir, oldDataDir); |
328 | |
} |
329 | 0 | } |
330 | |
|
331 | |
private static boolean migrate(File oldPath, File newPath) { |
332 | 0 | if (oldPath.equals(newPath) || !oldPath.exists()) { |
333 | 0 | return true; |
334 | |
} |
335 | |
|
336 | |
|
337 | 0 | File parent = newPath.getParentFile(); |
338 | 0 | if (!parent.exists() && !parent.mkdirs()) { |
339 | 0 | return false; |
340 | |
} |
341 | |
|
342 | 0 | return oldPath.renameTo(newPath); |
343 | |
} |
344 | |
|
345 | |
|
346 | |
|
347 | |
|
348 | |
|
349 | |
|
350 | |
|
351 | |
public static File getSwordDownloadDir() { |
352 | 0 | if (overrideDownloadDir != null) { |
353 | 0 | return overrideDownloadDir; |
354 | |
} |
355 | 0 | return defaultDownloadDir; |
356 | |
} |
357 | |
|
358 | |
|
359 | |
|
360 | |
|
361 | |
public static File getDownloadDir() { |
362 | 0 | return overrideDownloadDir; |
363 | |
} |
364 | |
|
365 | |
|
366 | |
|
367 | |
|
368 | |
|
369 | |
public static void setDownloadDir(File dlDir) { |
370 | 0 | if (!"".equals(dlDir.getPath())) { |
371 | 0 | overrideDownloadDir = dlDir; |
372 | 0 | log.debug("Setting sword download directory to: {}", dlDir); |
373 | |
} |
374 | 0 | } |
375 | |
|
376 | |
|
377 | |
|
378 | |
|
379 | |
|
380 | 0 | static class CustomFilenameFilter implements FilenameFilter { |
381 | |
|
382 | |
|
383 | |
|
384 | |
|
385 | |
|
386 | |
public boolean accept(File parent, String name) { |
387 | 0 | return !name.startsWith(PREFIX_GLOBALS) && name.endsWith(SwordConstants.EXTENSION_CONF); |
388 | |
} |
389 | |
} |
390 | |
|
391 | |
|
392 | |
|
393 | |
|
394 | |
private static final String DIR_WINDOWS_DEFAULT = "C:\\Program Files\\CrossWire\\The SWORD Project"; |
395 | |
|
396 | |
|
397 | |
|
398 | |
|
399 | |
private static final String DIR_SWORD_LIBRARY = "library"; |
400 | |
|
401 | |
|
402 | |
|
403 | |
|
404 | |
private static final String DIR_SWORD_CONF = ".sword"; |
405 | |
|
406 | |
|
407 | |
|
408 | |
|
409 | |
private static final String DIR_SWORD_CONF_ALT = "Sword"; |
410 | |
|
411 | |
|
412 | |
|
413 | |
|
414 | |
private static final String SWORD_GLOBAL_CONF = "sword.conf"; |
415 | |
|
416 | |
|
417 | |
|
418 | |
|
419 | |
private static final String DIR_SWORD_GLOBAL_CONF = "/etc:/usr/local/etc"; |
420 | |
|
421 | |
|
422 | |
|
423 | |
|
424 | |
private static final String DATA_PATH = "DataPath"; |
425 | |
|
426 | |
|
427 | |
|
428 | |
|
429 | |
private static final String AUGMENT_PATH = "AugmentPath"; |
430 | |
|
431 | |
|
432 | |
|
433 | |
|
434 | |
private static final String PROPERTY_SWORD_HOME = "sword.home"; |
435 | |
|
436 | |
|
437 | |
|
438 | |
|
439 | |
private static final String PROPERTY_USER_HOME = "user.home"; |
440 | |
|
441 | |
|
442 | |
|
443 | |
|
444 | |
private static final String PREFIX_GLOBALS = "globals."; |
445 | |
|
446 | |
|
447 | |
|
448 | |
|
449 | 0 | private static File[] augmentPath = new File[0]; |
450 | |
|
451 | |
|
452 | |
|
453 | |
|
454 | 0 | private static File defaultDownloadDir = getDefaultDownloadPath(); |
455 | |
|
456 | |
|
457 | |
|
458 | |
|
459 | |
private static File overrideDownloadDir; |
460 | |
|
461 | |
|
462 | |
|
463 | |
|
464 | 0 | private static final Logger log = LoggerFactory.getLogger(SwordBookPath.class); |
465 | |
|
466 | |
} |