Makefile (better Android Studio support)
[nikiroo-utils.git] / src / be / nikiroo / fanfix / Instance.java
CommitLineData
08fe2e33
NR
1package be.nikiroo.fanfix;
2
3import java.io.File;
4import java.io.IOException;
b42117f1 5import java.util.Date;
08fe2e33
NR
6
7import be.nikiroo.fanfix.bundles.Config;
8import be.nikiroo.fanfix.bundles.ConfigBundle;
99ccbdf6 9import be.nikiroo.fanfix.bundles.StringId;
08fe2e33 10import be.nikiroo.fanfix.bundles.StringIdBundle;
b4dc6ab5
NR
11import be.nikiroo.fanfix.bundles.UiConfig;
12import be.nikiroo.fanfix.bundles.UiConfigBundle;
e42573a0 13import be.nikiroo.fanfix.library.BasicLibrary;
5895a958 14import be.nikiroo.fanfix.library.CacheLibrary;
e42573a0 15import be.nikiroo.fanfix.library.LocalLibrary;
e023483b 16import be.nikiroo.fanfix.library.RemoteLibrary;
581d42c0 17import be.nikiroo.utils.Cache;
b42117f1 18import be.nikiroo.utils.IOUtils;
581d42c0 19import be.nikiroo.utils.TraceHandler;
08fe2e33
NR
20import be.nikiroo.utils.resources.Bundles;
21
22/**
23 * Global state for the program (services and singletons).
24 *
25 * @author niki
26 */
27public class Instance {
28 private static ConfigBundle config;
b4dc6ab5 29 private static UiConfigBundle uiconfig;
08fe2e33 30 private static StringIdBundle trans;
f1fb834c 31 private static DataLoader cache;
e023483b 32 private static BasicLibrary lib;
08fe2e33 33 private static File coverDir;
3727aae2 34 private static File readerTmp;
b0e88ebd 35 private static File remoteDir;
b42117f1 36 private static String configDir;
581d42c0 37 private static TraceHandler tracer;
a8209dd0 38
08fe2e33 39 static {
62c63b07 40 // Before we can configure it:
ae78e517 41 tracer = new TraceHandler(true, checkEnv("DEBUG"), checkEnv("DEBUG"));
62c63b07 42
948637bc 43 // Most of the rest is dependent upon this:
08fe2e33
NR
44 config = new ConfigBundle();
45
b42117f1 46 configDir = System.getProperty("CONFIG_DIR");
22848428
NR
47 if (configDir == null) {
48 configDir = System.getenv("CONFIG_DIR");
49 }
b42117f1 50
fe999aa4 51 if (configDir == null) {
ae78e517 52 configDir = new File(getHome(), ".fanfix").getPath();
fe999aa4 53 }
39c3c689 54
b42117f1
NR
55 if (!new File(configDir).exists()) {
56 new File(configDir).mkdirs();
57 } else {
fe999aa4
NR
58 Bundles.setDirectory(configDir);
59 }
60
b42117f1
NR
61 try {
62 config = new ConfigBundle();
63 config.updateFile(configDir);
64 } catch (IOException e) {
62c63b07 65 tracer.error(e);
b42117f1
NR
66 }
67 try {
68 uiconfig = new UiConfigBundle();
69 uiconfig.updateFile(configDir);
70 } catch (IOException e) {
62c63b07 71 tracer.error(e);
b42117f1 72 }
99ccbdf6
NR
73
74 // No updateFile for this one! (we do not want the user to have custom
75 // translations that won't accept updates from newer versions)
76 trans = new StringIdBundle(getLang());
77
78 // Fix an old bug (we used to store custom translation files by
79 // default):
80 if (trans.getString(StringId.INPUT_DESC_CBZ) == null) {
ae78e517 81 trans.deleteFile(configDir);
b42117f1
NR
82 }
83
84 Bundles.setDirectory(configDir);
85
b4dc6ab5 86 uiconfig = new UiConfigBundle();
08fe2e33 87 trans = new StringIdBundle(getLang());
2206ef66 88
581d42c0
NR
89 boolean debug = Instance.getConfig()
90 .getBoolean(Config.DEBUG_ERR, false);
91 boolean trace = Instance.getConfig().getBoolean(Config.DEBUG_TRACE,
92 false);
08fe2e33 93 coverDir = getFile(Config.DEFAULT_COVERS_DIR);
3727aae2 94 File tmp = getFile(Config.CACHE_DIR);
b4dc6ab5 95 readerTmp = getFile(UiConfig.CACHE_DIR_LOCAL_READER);
e604986c 96 remoteDir = new File(configDir, "remote");
3727aae2 97
d0114000
NR
98 if (checkEnv("NOUTF")) {
99 trans.setUnicode(false);
100 }
101
102 if (checkEnv("DEBUG")) {
103 debug = true;
ae78e517 104 trace = true;
d0114000
NR
105 }
106
62c63b07 107 tracer = new TraceHandler(true, debug, trace);
581d42c0 108
e023483b
NR
109 String remoteLib = config.getString(Config.DEFAULT_LIBRARY);
110 if (remoteLib == null || remoteLib.trim().isEmpty()) {
b4f9071c
NR
111 String libDir = System.getProperty("fanfix.libdir");
112 if (libDir == null || libDir.isEmpty()) {
113 config.getString(Config.LIBRARY_DIR);
114 }
e023483b 115 try {
b4f9071c 116 lib = new LocalLibrary(getFile(libDir));
e023483b
NR
117 } catch (Exception e) {
118 tracer.error(new IOException(
119 "Cannot create library for directory: "
b4f9071c 120 + getFile(libDir), e));
e023483b
NR
121 }
122 } else {
123 int pos = remoteLib.lastIndexOf(":");
124 if (pos >= 0) {
125 String port = remoteLib.substring(pos + 1).trim();
126 remoteLib = remoteLib.substring(0, pos);
127 pos = remoteLib.lastIndexOf(":");
128 if (pos >= 0) {
129 String host = remoteLib.substring(pos + 1).trim();
130 String key = remoteLib.substring(0, pos).trim();
131
132 try {
5895a958 133 tracer.trace("Selecting remote library " + host + ":"
e023483b
NR
134 + port);
135 lib = new RemoteLibrary(key, host,
136 Integer.parseInt(port));
5895a958
NR
137 lib = new CacheLibrary(getRemoteDir(host), lib);
138
e023483b
NR
139 } catch (Exception e) {
140 }
141 }
142 }
143
144 if (lib == null) {
145 tracer.error(new IOException(
ae78e517 146 "Cannot create remote library for: " + remoteLib));
e023483b 147 }
778d8d85
NR
148 }
149
68e370a4
NR
150 // Could have used: System.getProperty("java.io.tmpdir")
151 if (tmp == null) {
152 tmp = new File(configDir, "tmp");
153 }
154 if (readerTmp == null) {
155 readerTmp = new File(configDir, "tmp-reader");
3727aae2 156 }
68e370a4 157 //
08fe2e33
NR
158
159 if (coverDir != null && !coverDir.exists()) {
62c63b07 160 tracer.error(new IOException(
08fe2e33
NR
161 "The 'default covers' directory does not exists: "
162 + coverDir));
163 coverDir = null;
164 }
08fe2e33 165
ae78e517 166 String ua = config.getString(Config.USER_AGENT);
08fe2e33 167 try {
08fe2e33
NR
168 int hours = config.getInteger(Config.CACHE_MAX_TIME_CHANGING, -1);
169 int hoursLarge = config
170 .getInteger(Config.CACHE_MAX_TIME_STABLE, -1);
f1fb834c 171 cache = new DataLoader(tmp, ua, hours, hoursLarge);
08fe2e33 172 } catch (IOException e) {
62c63b07 173 tracer.error(new IOException(
08fe2e33 174 "Cannot create cache (will continue without cache)", e));
ae78e517 175 cache = new DataLoader(ua);
08fe2e33 176 }
ae78e517
NR
177
178 cache.setTraceHandler(tracer);
08fe2e33
NR
179 }
180
581d42c0
NR
181 /**
182 * The traces handler for this {@link Cache}.
62c63b07
NR
183 * <p>
184 * It is never NULL.
581d42c0 185 *
62c63b07 186 * @return the traces handler (never NULL)
581d42c0
NR
187 */
188 public static TraceHandler getTraceHandler() {
189 return tracer;
190 }
191
192 /**
193 * The traces handler for this {@link Cache}.
194 *
195 * @param tracer
196 * the new traces handler or NULL
197 */
198 public static void setTraceHandler(TraceHandler tracer) {
62c63b07
NR
199 if (tracer == null) {
200 tracer = new TraceHandler(false, false, false);
201 }
202
581d42c0 203 Instance.tracer = tracer;
ae78e517 204 cache.setTraceHandler(tracer);
581d42c0
NR
205 }
206
08fe2e33
NR
207 /**
208 * Get the (unique) configuration service for the program.
209 *
210 * @return the configuration service
211 */
212 public static ConfigBundle getConfig() {
213 return config;
214 }
215
b4dc6ab5
NR
216 /**
217 * Get the (unique) UI configuration service for the program.
218 *
219 * @return the configuration service
220 */
221 public static UiConfigBundle getUiConfig() {
222 return uiconfig;
223 }
224
ae78e517
NR
225 /**
226 * Reset the configuration.
227 *
228 * @param resetTrans
229 * also reset the translation files
230 */
231 public static void resetConfig(boolean resetTrans) {
232 String dir = Bundles.getDirectory();
233 Bundles.setDirectory(null);
234 try {
235 try {
236 ConfigBundle config = new ConfigBundle();
237 config.updateFile(configDir);
238 } catch (IOException e) {
239 tracer.error(e);
240 }
241 try {
242 UiConfigBundle uiconfig = new UiConfigBundle();
243 uiconfig.updateFile(configDir);
244 } catch (IOException e) {
245 tracer.error(e);
246 }
247
248 if (resetTrans) {
249 try {
250 StringIdBundle trans = new StringIdBundle(null);
251 trans.updateFile(configDir);
252 } catch (IOException e) {
253 tracer.error(e);
254 }
255 }
256 } finally {
257 Bundles.setDirectory(dir);
258 }
259 }
260
08fe2e33 261 /**
f1fb834c 262 * Get the (unique) {@link DataLoader} for the program.
08fe2e33 263 *
f1fb834c 264 * @return the {@link DataLoader}
08fe2e33 265 */
f1fb834c 266 public static DataLoader getCache() {
08fe2e33
NR
267 return cache;
268 }
269
270 /**
271 * Get the (unique) {link StringIdBundle} for the program.
39c3c689 272 *
08fe2e33
NR
273 * @return the {link StringIdBundle}
274 */
275 public static StringIdBundle getTrans() {
276 return trans;
277 }
278
279 /**
68e2c6d2 280 * Get the (unique) {@link LocalLibrary} for the program.
08fe2e33 281 *
68e2c6d2 282 * @return the {@link LocalLibrary}
08fe2e33 283 */
68e2c6d2 284 public static BasicLibrary getLibrary() {
778d8d85
NR
285 if (lib == null) {
286 throw new NullPointerException("We don't have a library to return");
287 }
288
08fe2e33
NR
289 return lib;
290 }
291
292 /**
293 * Return the directory where to look for default cover pages.
294 *
295 * @return the default covers directory
296 */
297 public static File getCoverDir() {
298 return coverDir;
299 }
300
3727aae2
NR
301 /**
302 * Return the directory where to store temporary files for the local reader.
303 *
304 * @return the directory
305 */
306 public static File getReaderDir() {
307 return readerTmp;
308 }
309
b0e88ebd
NR
310 /**
311 * Return the directory where to store temporary files for the remote
68e2c6d2 312 * {@link LocalLibrary}.
b0e88ebd
NR
313 *
314 * @param host
315 * the remote for this host
316 *
317 * @return the directory
318 */
319 public static File getRemoteDir(String host) {
320 remoteDir.mkdirs();
321
322 if (host != null) {
323 return new File(remoteDir, host);
324 }
325
326 return remoteDir;
327 }
328
b42117f1
NR
329 /**
330 * Check if we need to check that a new version of Fanfix is available.
331 *
332 * @return TRUE if we need to
333 */
334 public static boolean isVersionCheckNeeded() {
335 try {
a3641e4b
NR
336 long wait = config.getInteger(Config.UPDATE_INTERVAL, 1) * 24 * 60
337 * 60 * 1000;
b42117f1
NR
338 if (wait >= 0) {
339 String lastUpString = IOUtils.readSmallFile(new File(configDir,
340 "LAST_UPDATE"));
341 long delay = new Date().getTime()
342 - Long.parseLong(lastUpString);
343 if (delay > wait) {
344 return true;
345 }
346 } else {
347 return false;
348 }
349 } catch (Exception e) {
350 // No file or bad file:
351 return true;
352 }
353
354 return false;
355 }
356
357 /**
358 * Notify that we checked for a new version of Fanfix.
359 */
360 public static void setVersionChecked() {
361 try {
362 IOUtils.writeSmallFile(new File(configDir), "LAST_UPDATE",
363 Long.toString(new Date().getTime()));
364 } catch (IOException e) {
581d42c0 365 tracer.error(e);
08fe2e33
NR
366 }
367 }
368
369 /**
370 * Return a path, but support the special $HOME variable.
371 *
372 * @return the path
373 */
374 private static File getFile(Config id) {
b4dc6ab5
NR
375 return getFile(config.getString(id));
376 }
377
378 /**
379 * Return a path, but support the special $HOME variable.
380 *
381 * @return the path
382 */
383 private static File getFile(UiConfig id) {
384 return getFile(uiconfig.getString(id));
385 }
386
387 /**
388 * Return a path, but support the special $HOME variable.
389 *
390 * @return the path
391 */
392 private static File getFile(String path) {
08fe2e33 393 File file = null;
08fe2e33
NR
394 if (path != null && !path.isEmpty()) {
395 path = path.replace('/', File.separatorChar);
396 if (path.contains("$HOME")) {
ae78e517 397 path = path.replace("$HOME", getHome());
08fe2e33
NR
398 }
399
400 file = new File(path);
401 }
402
403 return file;
404 }
405
ae78e517
NR
406 /**
407 * Return the home directory from the system properties.
408 *
409 * @return the home
410 */
411 private static String getHome() {
b4f9071c
NR
412 String home = System.getProperty("fanfix.home");
413 if (home != null && new File(home).isFile()) {
414 home = null;
415 }
416
417 if (home == null || home.trim().isEmpty()) {
418 home = System.getProperty("user.home");
419 if (!new File(home).isDirectory()) {
420 home = null;
421 }
422 }
423
ae78e517
NR
424 if (home == null || home.trim().isEmpty()) {
425 home = System.getProperty("java.io.tmpdir");
b4f9071c
NR
426 if (!new File(home).isDirectory()) {
427 home = null;
428 }
ae78e517
NR
429 }
430
431 if (home == null) {
432 home = "";
433 }
434
435 return home;
436 }
437
08fe2e33
NR
438 /**
439 * The language to use for the application (NULL = default system language).
440 *
441 * @return the language
442 */
443 private static String getLang() {
444 String lang = config.getString(Config.LANG);
445
446 if (System.getenv("LANG") != null && !System.getenv("LANG").isEmpty()) {
447 lang = System.getenv("LANG");
448 }
449
450 if (lang != null && lang.isEmpty()) {
451 lang = null;
452 }
453
454 return lang;
455 }
d0114000
NR
456
457 /**
458 * Check that the given environment variable is "enabled".
459 *
460 * @param key
461 * the variable to check
462 *
463 * @return TRUE if it is
464 */
465 private static boolean checkEnv(String key) {
466 String value = System.getenv(key);
467 if (value != null) {
468 value = value.trim().toLowerCase();
469 if ("yes".equals(value) || "true".equals(value)
470 || "on".equals(value) || "1".equals(value)
471 || "y".equals(value)) {
472 return true;
473 }
474 }
475
476 return false;
477 }
08fe2e33 478}