1 package be
.nikiroo
.fanfix
;
4 import java
.io
.IOException
;
7 import be
.nikiroo
.fanfix
.bundles
.Config
;
8 import be
.nikiroo
.fanfix
.bundles
.ConfigBundle
;
9 import be
.nikiroo
.fanfix
.bundles
.StringId
;
10 import be
.nikiroo
.fanfix
.bundles
.StringIdBundle
;
11 import be
.nikiroo
.fanfix
.bundles
.UiConfig
;
12 import be
.nikiroo
.fanfix
.bundles
.UiConfigBundle
;
13 import be
.nikiroo
.fanfix
.library
.BasicLibrary
;
14 import be
.nikiroo
.fanfix
.library
.LocalLibrary
;
15 import be
.nikiroo
.fanfix
.output
.BasicOutput
.OutputType
;
16 import be
.nikiroo
.utils
.IOUtils
;
17 import be
.nikiroo
.utils
.resources
.Bundles
;
20 * Global state for the program (services and singletons).
24 public class Instance
{
26 * A handler when a recoverable exception was caught by the program.
30 public interface SyserrHandler
{
32 * An exception happened, log it.
37 * show more details (usually equivalent to the value of
40 public void notify(Exception e
, boolean showDetails
);
44 * A handler when a trace message is sent.
48 public interface TraceHandler
{
50 * A trace happened, show it.
52 * Will only be called if TRACE is true.
57 public void trace(String message
);
60 private static ConfigBundle config
;
61 private static UiConfigBundle uiconfig
;
62 private static StringIdBundle trans
;
63 private static DataLoader cache
;
64 private static LocalLibrary lib
;
65 private static boolean debug
;
66 private static boolean trace
;
67 private static File coverDir
;
68 private static File readerTmp
;
69 private static File remoteDir
;
70 private static String configDir
;
72 private static SyserrHandler syserrHandler
;
74 private static TraceHandler traceHandler
;
77 // Most of the rest is dependent upon this:
78 config
= new ConfigBundle();
80 configDir
= System
.getProperty("CONFIG_DIR");
81 if (configDir
== null) {
82 configDir
= System
.getenv("CONFIG_DIR");
85 if (configDir
== null) {
86 configDir
= new File(System
.getProperty("user.home"), ".fanfix")
90 if (!new File(configDir
).exists()) {
91 new File(configDir
).mkdirs();
93 Bundles
.setDirectory(configDir
);
97 config
= new ConfigBundle();
98 config
.updateFile(configDir
);
99 } catch (IOException e
) {
103 uiconfig
= new UiConfigBundle();
104 uiconfig
.updateFile(configDir
);
105 } catch (IOException e
) {
109 // No updateFile for this one! (we do not want the user to have custom
110 // translations that won't accept updates from newer versions)
111 trans
= new StringIdBundle(getLang());
113 // Fix an old bug (we used to store custom translation files by
115 if (trans
.getString(StringId
.INPUT_DESC_CBZ
) == null) {
116 // TODO: create the deleteFile method
117 // trans.deleteFile(configDir);
120 Bundles
.setDirectory(configDir
);
122 uiconfig
= new UiConfigBundle();
123 trans
= new StringIdBundle(getLang());
125 lib
= new LocalLibrary(getFile(Config
.LIBRARY_DIR
),
126 OutputType
.INFO_TEXT
, OutputType
.CBZ
);
127 } catch (Exception e
) {
128 syserr(new IOException("Cannot create library for directory: "
129 + getFile(Config
.LIBRARY_DIR
), e
));
132 debug
= Instance
.getConfig().getBoolean(Config
.DEBUG_ERR
, false);
133 trace
= Instance
.getConfig().getBoolean(Config
.DEBUG_TRACE
, false);
134 coverDir
= getFile(Config
.DEFAULT_COVERS_DIR
);
135 File tmp
= getFile(Config
.CACHE_DIR
);
136 readerTmp
= getFile(UiConfig
.CACHE_DIR_LOCAL_READER
);
137 remoteDir
= new File(getFile(Config
.LIBRARY_DIR
), "remote");
139 if (checkEnv("NOUTF")) {
140 trans
.setUnicode(false);
143 if (checkEnv("DEBUG")) {
147 // Could have used: System.getProperty("java.io.tmpdir")
149 tmp
= new File(configDir
, "tmp");
151 if (readerTmp
== null) {
152 readerTmp
= new File(configDir
, "tmp-reader");
156 if (coverDir
!= null && !coverDir
.exists()) {
157 syserr(new IOException(
158 "The 'default covers' directory does not exists: "
164 String ua
= config
.getString(Config
.USER_AGENT
);
165 int hours
= config
.getInteger(Config
.CACHE_MAX_TIME_CHANGING
, -1);
166 int hoursLarge
= config
167 .getInteger(Config
.CACHE_MAX_TIME_STABLE
, -1);
169 cache
= new DataLoader(tmp
, ua
, hours
, hoursLarge
);
170 } catch (IOException e
) {
171 syserr(new IOException(
172 "Cannot create cache (will continue without cache)", e
));
177 * Get the (unique) configuration service for the program.
179 * @return the configuration service
181 public static ConfigBundle
getConfig() {
186 * Get the (unique) UI configuration service for the program.
188 * @return the configuration service
190 public static UiConfigBundle
getUiConfig() {
195 * Get the (unique) {@link DataLoader} for the program.
197 * @return the {@link DataLoader}
199 public static DataLoader
getCache() {
204 * Get the (unique) {link StringIdBundle} for the program.
206 * @return the {link StringIdBundle}
208 public static StringIdBundle
getTrans() {
213 * Get the (unique) {@link LocalLibrary} for the program.
215 * @return the {@link LocalLibrary}
217 public static BasicLibrary
getLibrary() {
222 * Return the directory where to look for default cover pages.
224 * @return the default covers directory
226 public static File
getCoverDir() {
231 * Return the directory where to store temporary files for the local reader.
233 * @return the directory
235 public static File
getReaderDir() {
240 * Return the directory where to store temporary files for the remote
241 * {@link LocalLibrary}.
244 * the remote for this host
246 * @return the directory
248 public static File
getRemoteDir(String host
) {
252 return new File(remoteDir
, host
);
259 * Check if we need to check that a new version of Fanfix is available.
261 * @return TRUE if we need to
263 public static boolean isVersionCheckNeeded() {
265 long wait
= config
.getInteger(Config
.UPDATE_INTERVAL
, 1) * 24 * 60
268 String lastUpString
= IOUtils
.readSmallFile(new File(configDir
,
270 long delay
= new Date().getTime()
271 - Long
.parseLong(lastUpString
);
278 } catch (Exception e
) {
279 // No file or bad file:
287 * Notify that we checked for a new version of Fanfix.
289 public static void setVersionChecked() {
291 IOUtils
.writeSmallFile(new File(configDir
), "LAST_UPDATE",
292 Long
.toString(new Date().getTime()));
293 } catch (IOException e
) {
299 * Replace the global syserr handler.
301 * @param syserrHandler
302 * the new syserr handler
304 public static void setSyserrHandler(SyserrHandler syserrHandler
) {
305 Instance
.syserrHandler
= syserrHandler
;
309 * Replace the global trace handler.
311 * @param traceHandler
312 * the new trace handler
314 public static void setTraceHandler(TraceHandler traceHandler
) {
315 Instance
.traceHandler
= traceHandler
;
319 * Report an error to the user
322 * the {@link Exception} to report
324 public static void syserr(Exception e
) {
325 if (syserrHandler
!= null) {
326 syserrHandler
.notify(e
, debug
);
331 System
.err
.println(e
.getMessage());
337 * Notify of a debug message.
342 public static void trace(String message
) {
344 if (traceHandler
!= null) {
345 traceHandler
.trace(message
);
347 System
.out
.println(message
);
353 * Return a path, but support the special $HOME variable.
357 private static File
getFile(Config id
) {
358 return getFile(config
.getString(id
));
362 * Return a path, but support the special $HOME variable.
366 private static File
getFile(UiConfig id
) {
367 return getFile(uiconfig
.getString(id
));
371 * Return a path, but support the special $HOME variable.
375 private static File
getFile(String path
) {
377 if (path
!= null && !path
.isEmpty()) {
378 path
= path
.replace('/', File
.separatorChar
);
379 if (path
.contains("$HOME")) {
380 path
= path
.replace("$HOME",
381 "" + System
.getProperty("user.home"));
384 file
= new File(path
);
391 * The language to use for the application (NULL = default system language).
393 * @return the language
395 private static String
getLang() {
396 String lang
= config
.getString(Config
.LANG
);
398 if (System
.getenv("LANG") != null && !System
.getenv("LANG").isEmpty()) {
399 lang
= System
.getenv("LANG");
402 if (lang
!= null && lang
.isEmpty()) {
410 * Check that the given environment variable is "enabled".
413 * the variable to check
415 * @return TRUE if it is
417 private static boolean checkEnv(String key
) {
418 String value
= System
.getenv(key
);
420 value
= value
.trim().toLowerCase();
421 if ("yes".equals(value
) || "true".equals(value
)
422 || "on".equals(value
) || "1".equals(value
)
423 || "y".equals(value
)) {