update to latest nikiroo-utils
[jvcard.git] / src / be / nikiroo / jvcard / launcher / Main.java
CommitLineData
7da41ecd
NR
1package be.nikiroo.jvcard.launcher;
2
3import java.io.File;
4import java.io.IOException;
5import java.lang.reflect.Field;
7da41ecd
NR
6import java.net.Socket;
7import java.nio.charset.Charset;
8import java.util.LinkedList;
9import java.util.List;
10
11import be.nikiroo.jvcard.Card;
26d254a3
NR
12import be.nikiroo.jvcard.Contact;
13import be.nikiroo.jvcard.Data;
14import be.nikiroo.jvcard.TypeInfo;
5ad0e17e 15import be.nikiroo.jvcard.launcher.CardResult.MergeCallback;
e643219c 16import be.nikiroo.jvcard.launcher.Optional.NotSupportedException;
7da41ecd 17import be.nikiroo.jvcard.parsers.Format;
845fb1d7 18import be.nikiroo.jvcard.remote.Command;
7da41ecd 19import be.nikiroo.jvcard.remote.SimpleSocket;
f06c8100
NR
20import be.nikiroo.jvcard.resources.DisplayBundle;
21import be.nikiroo.jvcard.resources.DisplayOption;
22import be.nikiroo.jvcard.resources.RemoteBundle;
23import be.nikiroo.jvcard.resources.StringId;
24import be.nikiroo.jvcard.resources.TransBundle;
24e66f83
NR
25import be.nikiroo.utils.IOUtils;
26import be.nikiroo.utils.Image;
f06c8100
NR
27import be.nikiroo.utils.ImageUtils;
28import be.nikiroo.utils.StringUtils;
29import be.nikiroo.utils.Version;
30import be.nikiroo.utils.resources.Bundles;
7da41ecd
NR
31
32/**
33 * This class contains the runnable Main method. It will parse the user supplied
34 * parameters and take action based upon those. Most of the time, it will start
35 * a MainWindow.
36 *
37 * @author niki
f06c8100 38 *
7da41ecd
NR
39 */
40public class Main {
24e66f83 41 /** The name of the program */
7da41ecd 42 static public final String APPLICATION_TITLE = "jVcard";
7da41ecd
NR
43
44 static private final int ERR_NO_FILE = 1;
45 static private final int ERR_SYNTAX = 2;
46 static private final int ERR_INTERNAL = 3;
e119a1c1 47 static private TransBundle transService;
7da41ecd 48
30a4aa17
NR
49 static private String defaultFn;
50 static private boolean forceComputedFn;
51
26d254a3 52 enum Mode {
812124d1 53 CONTACT_MANAGER, I18N, SERVER, LOAD_PHOTO, SAVE_PHOTO, SAVE_CONFIG, HELP, SAVE_TO,
26d254a3
NR
54 }
55
7da41ecd 56 /**
9b8cb729 57 * Translate the given {@link StringId} into user text.
7da41ecd 58 *
5c5abfd2 59 * @param id
7da41ecd 60 * the ID to translate
9b8cb729
NR
61 * @param values
62 * the values to insert instead of the place holders in the
63 * translation
7da41ecd 64 *
9b8cb729 65 * @return the translated text with the given value where required
7da41ecd 66 */
e119a1c1 67 static public String trans(StringId id, Object... values) {
59597d59 68 return transService.getString(id, values);
7da41ecd
NR
69 }
70
71 /**
72 * Check if unicode characters should be used.
73 *
74 * @return TRUE to allow unicode
75 */
76 static public boolean isUnicode() {
77 return transService.isUnicode();
78 }
79
80 /**
81 * Start the application.
82 *
83 * <p>
84 * The returned exit codes are:
85 * <ul>
86 * <li>1: no files to open</li>
87 * <li>2: invalid syntax</li>
88 * <li>3: internal error</li>
89 * </ul>
90 * </p>
91 *
92 * @param args
93 * the parameters (see <tt>--help</tt> to know which are
94 * supported)
95 */
96 public static void main(String[] args) {
97 Boolean textMode = null;
98 boolean noMoreParams = false;
99 boolean filesTried = false;
100
101 // get the "system default" language to help translate the --help
102 // message if needed
103 String language = null;
e119a1c1 104 transService = new TransBundle(language);
7da41ecd
NR
105
106 boolean unicode = transService.isUnicode();
26d254a3 107 String dir = null;
7da41ecd 108 List<String> files = new LinkedList<String>();
26d254a3
NR
109 int port = -1;
110 Mode mode = Mode.CONTACT_MANAGER;
111 String format = null;
812124d1 112 String output = null;
7da41ecd
NR
113 for (int index = 0; index < args.length; index++) {
114 String arg = args[index];
115 if (!noMoreParams && arg.equals("--")) {
116 noMoreParams = true;
117 } else if (!noMoreParams && arg.equals("--help")) {
88eb8122
NR
118 if (mode != Mode.CONTACT_MANAGER) {
119 SERR(StringId.CLI_SERR_MODES);
120 return;
121 }
122 mode = Mode.HELP;
7da41ecd
NR
123 } else if (!noMoreParams && arg.equals("--tui")) {
124 textMode = true;
125 } else if (!noMoreParams && arg.equals("--gui")) {
126 textMode = false;
127 } else if (!noMoreParams && arg.equals("--noutf")) {
128 unicode = false;
129 transService.setUnicode(unicode);
130 } else if (!noMoreParams && arg.equals("--lang")) {
131 index++;
132 if (index >= args.length) {
88eb8122 133 SERR(StringId.CLI_SERR_NOLANG);
7da41ecd
NR
134 return;
135 }
136
137 language = args[index];
e119a1c1 138 transService = new TransBundle(language);
7da41ecd
NR
139 transService.setUnicode(unicode);
140 } else if (!noMoreParams && arg.equals("--config")) {
141 index++;
142 if (index >= args.length) {
88eb8122 143 SERR(StringId.CLI_SERR_NODIR);
7da41ecd
NR
144 return;
145 }
146
147 Bundles.setDirectory(args[index]);
e119a1c1 148 transService = new TransBundle(language);
7da41ecd 149 transService.setUnicode(unicode);
e119a1c1
NR
150 } else if (!noMoreParams && arg.equals("--save-config")) {
151 index++;
152 if (index >= args.length) {
88eb8122 153 SERR(StringId.CLI_SERR_NODIR);
e119a1c1
NR
154 return;
155 }
156 dir = args[index];
157
158 if (mode != Mode.CONTACT_MANAGER) {
88eb8122 159 SERR(StringId.CLI_SERR_MODES);
e119a1c1
NR
160 return;
161 }
162 mode = Mode.SAVE_CONFIG;
7da41ecd 163 } else if (!noMoreParams && arg.equals("--server")) {
26d254a3 164 if (mode != Mode.CONTACT_MANAGER) {
88eb8122 165 SERR(StringId.CLI_SERR_MODES);
26d254a3
NR
166 return;
167 }
168 mode = Mode.SERVER;
169
7da41ecd
NR
170 index++;
171 if (index >= args.length) {
88eb8122 172 SERR(StringId.CLI_SERR_NOPORT);
7da41ecd
NR
173 return;
174 }
175
176 try {
177 port = Integer.parseInt(args[index]);
178 } catch (NumberFormatException e) {
88eb8122 179 SERR(StringId.CLI_SERR_BADPORT, "" + args[index]);
7da41ecd
NR
180 return;
181 }
182 } else if (!noMoreParams && arg.equals("--i18n")) {
26d254a3 183 if (mode != Mode.CONTACT_MANAGER) {
88eb8122 184 SERR(StringId.CLI_SERR_MODES);
26d254a3
NR
185 return;
186 }
187 mode = Mode.I18N;
188
7da41ecd
NR
189 index++;
190 if (index >= args.length) {
88eb8122 191 SERR(StringId.CLI_SERR_NODIR);
7da41ecd
NR
192 return;
193 }
9b8cb729 194
26d254a3
NR
195 dir = args[index];
196 } else if (!noMoreParams
197 && (arg.equals("--load-photo")
198 || arg.equals("--save-photo") || arg
199 .equals("--only-photo"))) {
200 if (mode != Mode.CONTACT_MANAGER) {
88eb8122 201 SERR(StringId.CLI_SERR_MODES);
26d254a3
NR
202 return;
203 }
204
205 if (arg.equals("--load-photo")) {
206 mode = Mode.LOAD_PHOTO;
207 } else if (arg.equals("--save-photo")) {
208 mode = Mode.SAVE_PHOTO;
26d254a3
NR
209 }
210
211 index++;
212 if (index >= args.length) {
88eb8122 213 SERR(StringId.CLI_SERR_NODIR);
26d254a3
NR
214 return;
215 }
216
217 dir = args[index];
218
219 index++;
220 if (index >= args.length) {
88eb8122 221 SERR(StringId.CLI_SERR_NOFORMAT);
26d254a3
NR
222 return;
223 }
224
225 format = args[index];
812124d1
NR
226 } else if (!noMoreParams && (arg.equals("--save-to"))) {
227 if (mode != Mode.CONTACT_MANAGER) {
228 SERR(StringId.CLI_SERR_MODES);
229 return;
230 }
231 mode = Mode.SAVE_TO;
232
233 index++;
234 if (index >= args.length) {
235 SERR(StringId.CLI_ERR_NOFILES);
236 return;
237 }
238
239 output = args[index];
7da41ecd
NR
240 } else {
241 filesTried = true;
242 files.addAll(open(arg));
243 }
244 }
9b8cb729 245
f578f3af 246 // Force headless mode if we run in forced-text mode
26d254a3 247 if (mode != Mode.CONTACT_MANAGER || (textMode != null && textMode)) {
f578f3af
NR
248 // same as -Djava.awt.headless=true
249 System.setProperty("java.awt.headless", "true");
250 }
7da41ecd
NR
251
252 if (unicode) {
253 utf8();
254 }
255
30a4aa17
NR
256 // N/FN fix information:
257 readNFN();
258
7da41ecd 259 // Error management:
26d254a3 260 if (mode == Mode.SERVER && files.size() > 0) {
88eb8122
NR
261 SERR(StringId.CLI_SERR_NOLANG, "--server");
262 return;
26d254a3 263 } else if (mode == Mode.I18N && files.size() > 0) {
88eb8122
NR
264 SERR(StringId.CLI_SERR_NOLANG, "--i18n");
265 return;
26d254a3 266 } else if (mode == Mode.I18N && language == null) {
88eb8122 267 SERR(StringId.CLI_SERR_NOLANG);
26d254a3
NR
268 } else if ((mode == Mode.CONTACT_MANAGER || mode == Mode.SAVE_PHOTO || mode == Mode.LOAD_PHOTO)
269 && files.size() == 0) {
7da41ecd
NR
270 if (files.size() == 0 && !filesTried) {
271 files.addAll(open("."));
272 }
273
274 if (files.size() == 0) {
88eb8122 275 ERR(StringId.CLI_ERR, StringId.CLI_ERR_NOFILES, ERR_NO_FILE);
7da41ecd
NR
276 return;
277 }
278 }
279 //
280
26d254a3 281 switch (mode) {
e119a1c1
NR
282 case SAVE_CONFIG: {
283 try {
284 if (!new File(dir).isDirectory()) {
285 if (!new File(dir).mkdir()) {
88eb8122
NR
286 System.err.println(trans(
287 StringId.CLI_ERR_CANNOT_CREATE_CONFDIR, dir));
e119a1c1
NR
288 }
289 }
290
e27d1404 291 new TransBundle().updateFile(dir); // default locale
f06c8100 292 for (String lang : new TransBundle().getKnownLanguages()) {
e27d1404
NR
293 new TransBundle(lang).updateFile(dir);
294 }
295
f06c8100 296 // new UIColors().updateFile(dir);
e119a1c1
NR
297 new DisplayBundle().updateFile(dir);
298 new RemoteBundle().updateFile(dir);
299 } catch (IOException e) {
300 e.printStackTrace();
59597d59 301 System.err.flush();
e119a1c1
NR
302 System.exit(ERR_INTERNAL);
303 }
304 break;
305 }
26d254a3 306 case SERVER: {
7da41ecd 307 try {
02b341aa 308 Optional.runServer(port);
e643219c
NR
309 } catch (IOException e) {
310 ERR(StringId.CLI_ERR, StringId.CLI_ERR_CANNOT_START,
311 ERR_INTERNAL);
312 return;
313 } catch (NotSupportedException e) {
314 if (!e.isCompiledIn()) {
88eb8122
NR
315 ERR(StringId.CLI_ERR, StringId.CLI_ERR_NO_REMOTING,
316 ERR_INTERNAL);
317 return;
7da41ecd 318 }
d5260eeb
NR
319 e.printStackTrace();
320 ERR(StringId.CLI_ERR, StringId.CLI_ERR, ERR_INTERNAL);
321 return;
7da41ecd 322 }
26d254a3
NR
323 break;
324 }
325 case I18N: {
7da41ecd 326 try {
e119a1c1 327 transService.updateFile(dir);
7da41ecd 328 } catch (IOException e) {
d459d7e1
NR
329 ERR(StringId.CLI_ERR, StringId.CLI_ERR_CANNOT_CREATE_LANG,
330 ERR_INTERNAL);
331 return;
7da41ecd 332 }
26d254a3
NR
333 break;
334 }
26d254a3
NR
335 case LOAD_PHOTO: {
336 for (String file : files) {
337 try {
338 Card card = getCard(file, null).getCard();
339 for (Contact contact : card) {
340 String filename = contact.toString(format, "");
f29274a7 341 File f = new File(dir, filename);
26d254a3
NR
342
343 if (f.exists()) {
e3fe9834 344 System.out.println("Loading " + f);
26d254a3 345 try {
a1783d00
NR
346 String type = "jpeg";
347 int dotIndex = filename.indexOf('.');
348 if (dotIndex >= 0
349 && (dotIndex + 1) < filename.length()) {
350 type = filename.substring(dotIndex + 1)
351 .toLowerCase();
352 }
353
f06c8100 354 String b64;
24e66f83 355 Image img = new Image(IOUtils.toByteArray(f));
f06c8100 356 try {
24e66f83 357 b64 = img.toBase64();
f06c8100 358 } finally {
24e66f83 359 img.close();
f06c8100 360 }
26d254a3 361
88eb8122
NR
362 // remove previous photos:
363 for (Data photo = contact
364 .getPreferredData("PHOTO"); photo != null; photo = contact
365 .getPreferredData("PHOTO")) {
366 photo.delete();
26d254a3 367 }
88eb8122 368 //
26d254a3
NR
369
370 List<TypeInfo> types = new LinkedList<TypeInfo>();
371 types.add(new TypeInfo("ENCODING", "b"));
a1783d00 372 types.add(new TypeInfo("TYPE", type));
26d254a3
NR
373 Data photo = new Data(types, "PHOTO", b64, null);
374 contact.add(photo);
375 } catch (IOException e) {
376 System.err.println("Cannot read photo: "
377 + filename);
378 }
379 }
380 }
381 card.save();
382 } catch (IOException e) {
88eb8122
NR
383 System.err
384 .println(trans(StringId.CLI_ERR_CANNOT_OPEN, file));
26d254a3
NR
385 }
386 }
387 break;
388 }
389 case SAVE_PHOTO: {
390 for (String file : files) {
391 try {
392 Card card = getCard(file, null).getCard();
393 for (Contact contact : card) {
394 Data photo = contact.getPreferredData("PHOTO");
395 if (photo != null) {
396 String filename = contact.toString(format, "");
397 File f = new File(dir, filename + ".png");
e3fe9834 398 System.out.println("Saving " + f);
24e66f83 399 Image img = new Image(photo.getValue());
26d254a3 400 try {
24e66f83
NR
401 ImageUtils.getInstance().saveAsImage(img, f,
402 "png");
26d254a3 403 } catch (IOException e) {
88eb8122
NR
404 System.err.println(trans(
405 StringId.CLI_ERR_CANNOT_SAVE_PHOTO,
406 contact.getPreferredDataValue("FN")));
26d254a3
NR
407 }
408 }
409 }
410 } catch (IOException e) {
88eb8122
NR
411 System.err
412 .println(trans(StringId.CLI_ERR_CANNOT_OPEN, file));
26d254a3
NR
413 }
414 }
415 break;
416 }
417 case CONTACT_MANAGER: {
7da41ecd 418 try {
02b341aa 419 Optional.startTui(textMode, files);
e643219c
NR
420 } catch (IOException e) {
421 ERR(StringId.CLI_ERR, StringId.CLI_ERR_CANNOT_START,
422 ERR_NO_FILE);
423 return;
424 } catch (NotSupportedException e) {
425 if (!e.isCompiledIn()) {
88eb8122
NR
426 ERR(StringId.CLI_ERR, StringId.CLI_ERR_NO_TUI, ERR_INTERNAL);
427 return;
7da41ecd 428 }
d5260eeb
NR
429 e.printStackTrace();
430 ERR(StringId.CLI_ERR, StringId.CLI_ERR, ERR_INTERNAL);
431 return;
7da41ecd 432 }
26d254a3
NR
433 break;
434 }
812124d1
NR
435 case SAVE_TO: {
436 try {
437 Card total = new Card(null, getCardFormat(output));
438
439 for (String file : files) {
440 try {
441 Card card = getCard(file, null).getCard();
442 card.unlink();
443 while (card.size() > 0) {
444 total.add(card.remove(0));
445 }
446 } catch (IOException e) {
447 System.err.println(trans(StringId.CLI_ERR_CANNOT_OPEN,
448 file));
449 }
450 }
451
452 total.saveAs(new File(output), getCardFormat(output));
453 } catch (IOException e) {
454 System.err.println(trans(StringId.CLI_ERR_CANNOT_OPEN, output));
455 }
456
457 break;
458 }
88eb8122 459 case HELP: {
f06c8100
NR
460 System.out.println(APPLICATION_TITLE + " "
461 + Version.getCurrentVersion());
88eb8122
NR
462 System.out.println();
463
464 System.out.println(trans(StringId.CLI_HELP));
465 System.out.println();
466
467 System.out.println(trans(StringId.CLI_HELP_MODES));
468 System.out.println("\t--help : "
469 + trans(StringId.CLI_HELP_MODE_HELP));
470 System.out.println("\t(--tui|--gui) (--noutf) ... : "
471 + trans(StringId.CLI_HELP_MODE_CONTACT_MANAGER));
472 System.out.println("\t--server PORT ... : "
473 + trans(StringId.CLI_HELP_MODE_SERVER));
474 System.out.println("\t--save-config DIR : "
475 + trans(StringId.CLI_HELP_MODE_SAVE_CONFIG));
476 System.out.println("\t--i18n DIR ---lang LANG : "
477 + trans(StringId.CLI_HELP_MODE_I18N));
478 System.out.println("\t--load-photo DIR FORMAT ... : "
479 + trans(StringId.CLI_HELP_MODE_LOAD_PHOTO));
480 System.out.println("\t--save-photo DIR FORMAT ... : "
481 + trans(StringId.CLI_HELP_MODE_SAVE_PHOTO));
812124d1
NR
482 System.out.println("\t--save-to output(.vcf) ... : "
483 + trans(StringId.CLI_HELP_MODE_SAVE_TO));
88eb8122
NR
484 System.out.println();
485
486 System.out.println(trans(StringId.CLI_HELP_OPTIONS));
487 System.out.println("\t-- : " + trans(StringId.CLI_HELP_DD));
488 System.out.println("\t--lang LANG : "
489 + trans(StringId.CLI_HELP_LANG));
490 System.out.println("\t--tui : " + trans(StringId.CLI_HELP_TUI));
491 System.out.println("\t--gui : " + trans(StringId.CLI_HELP_GUI));
99f631de
NR
492 System.out.println("\t--noutf : "
493 + trans(StringId.CLI_HELP_NOUTF_OPTION));
88eb8122
NR
494 System.out.println("\t--config : "
495 + trans(StringId.CLI_HELP_CONFIG));
496 System.out.println();
497
498 System.out.println(trans(StringId.CLI_HELP_FOOTER));
499 System.out.println();
500
812124d1 501 break;
88eb8122 502 }
7da41ecd
NR
503 }
504 }
505
506 /**
507 * Return the {@link Card} corresponding to the given resource name -- a
30a4aa17
NR
508 * file or a remote jvcard URL.
509 *
510 * <p>
511 * Will also fix the FN if required (see display.properties).
512 * </p>
7da41ecd
NR
513 *
514 * @param input
515 * a filename or a remote jvcard url with named resource (e.g.:
516 * <tt>jvcard://localhost:4444/coworkers.vcf</tt>)
5ad0e17e
NR
517 * @param callback
518 * the {@link MergeCallback} to call in case of conflict, or NULL
519 * to disallow conflict management (the {@link Card} will not be
520 * allowed to synchronise in case of conflicts)
7da41ecd
NR
521 *
522 * @return the {@link Card}
523 *
524 * @throws IOException
525 * in case of IO error or remoting not available
526 */
5ad0e17e
NR
527 static public CardResult getCard(String input, MergeCallback callback)
528 throws IOException {
812124d1
NR
529 boolean remote = isFileRemote(input);
530 Format format = getCardFormat(input);
7da41ecd 531
5ad0e17e 532 CardResult card = null;
7da41ecd
NR
533 try {
534 if (remote) {
5ad0e17e 535 card = Optional.syncCard(input, callback);
7da41ecd 536 } else {
5ad0e17e
NR
537 card = new CardResult(new Card(new File(input), format), false,
538 false, false);
7da41ecd
NR
539 }
540 } catch (IOException ioe) {
541 throw ioe;
e643219c 542 } catch (NotSupportedException e) {
4298276a 543 throw new IOException("Remoting support not available", e);
7da41ecd
NR
544 }
545
30a4aa17
NR
546 // Fix the FN value
547 if (defaultFn != null) {
548 try {
549 for (Contact contact : card.getCard()) {
550 Data name = contact.getPreferredData("FN");
812124d1
NR
551 Data n = contact.getPreferredData("N");
552 boolean hasN = n != null && n.getValue().length() > 0;
30a4aa17 553 if (name == null || name.getValue().length() == 0
812124d1 554 || (forceComputedFn && hasN)) {
99f631de 555 name.setValue(contact.toString(defaultFn, "").trim());
30a4aa17
NR
556 }
557 }
558 } catch (Exception e) {
559 // sync failed -> getCard() throws.
560 // do not update.
561 }
562 }
563
7da41ecd
NR
564 return card;
565 }
566
812124d1
NR
567 static private boolean isFileRemote(String input) {
568 return input.contains("://");
569 }
570
571 static Format getCardFormat(String input) {
572 if (isFileRemote(input)) {
573 return Format.VCard21;
574 }
575
576 Format format = Format.Abook;
577 String ext = input;
578 if (ext.contains(".")) {
579 String tab[] = ext.split("\\.");
580 if (tab.length > 1 && tab[tab.length - 1].equalsIgnoreCase("vcf")) {
581 format = Format.VCard21;
582 }
583 }
584
585 return format;
586 }
587
7da41ecd
NR
588 /**
589 * Open the given path and add all its files if it is a directory or just
590 * this one if not to the returned list.
591 *
592 * @param path
593 * the path to open
594 *
595 * @return the list of opened files
596 */
597 static private List<String> open(String path) {
598 List<String> files = new LinkedList<String>();
599
600 if (path != null && path.startsWith("jvcard://")) {
601 if (path.endsWith("/")) {
602 files.addAll(list(path));
603 } else {
604 files.add(path);
605 }
606 } else {
607 File file = new File(path);
608 if (file.exists()) {
609 if (file.isDirectory()) {
610 for (File subfile : file.listFiles()) {
611 if (!subfile.isDirectory())
612 files.add(subfile.getAbsolutePath());
613 }
614 } else {
615 files.add(file.getAbsolutePath());
616 }
617 } else {
618 System.err.println("File or directory not found: \"" + path
619 + "\"");
620 }
621 }
622
623 return files;
624 }
625
626 /**
627 * List all the available {@link Card}s on the given network location (which
628 * is expected to be a jVCard remote server, obviously).
629 *
630 * @param path
631 * the jVCard remote server path (e.g.:
632 * <tt>jvcard://localhost:4444/</tt>)
633 *
634 * @return the list of {@link Card}s
635 */
636 static private List<String> list(String path) {
637 List<String> files = new LinkedList<String>();
638
639 try {
640 String host = path.split("\\:")[1].substring(2);
641 int port = Integer.parseInt(path.split("\\:")[2].replaceAll("/$",
642 ""));
643 SimpleSocket s = new SimpleSocket(new Socket(host, port),
644 "sync client");
645 s.open(true);
646
845fb1d7 647 s.sendCommand(Command.LIST_CARD);
7da41ecd
NR
648 for (String p : s.receiveBlock()) {
649 files.add(path
650 + p.substring(StringUtils.fromTime(0).length() + 1));
651 }
652 s.close();
653 } catch (Exception e) {
654 e.printStackTrace();
655 }
656
657 return files;
658 }
659
660 /**
661 * Really, really ask for UTF-8 encoding.
662 */
663 static private void utf8() {
664 try {
665 System.setProperty("file.encoding", "UTF-8");
666 Field charset = Charset.class.getDeclaredField("defaultCharset");
667 charset.setAccessible(true);
668 charset.set(null, null);
669 } catch (SecurityException e) {
670 } catch (NoSuchFieldException e) {
671 } catch (IllegalArgumentException e) {
672 } catch (IllegalAccessException e) {
673 }
674 }
30a4aa17
NR
675
676 /**
677 * Read display.properties to know if we should fix the FN field when empty,
678 * or always, or never.
679 */
680 static private void readNFN() {
e119a1c1 681 DisplayBundle map = new DisplayBundle();
30a4aa17 682
e119a1c1
NR
683 defaultFn = map.getString(DisplayOption.CONTACT_DETAILS_DEFAULT_FN);
684
685 forceComputedFn = map.getBoolean(
686 DisplayOption.CONTACT_DETAILS_SHOW_COMPUTED_FN, false);
30a4aa17 687 }
88eb8122
NR
688
689 /**
690 * Syntax error detected, closing the application with an error message.
691 *
692 * @param err
693 * the syntax error case
694 */
695 static private void SERR(StringId err, Object... values) {
696 ERR(StringId.CLI_SERR, err, ERR_SYNTAX, values);
697 }
698
699 /**
700 * Error detected, closing the application with an error message.
701 *
702 * @param err
703 * the error case
704 * @param suberr
705 * the suberror or NULL if none
706 * @param CODE
707 * the error code as declared above
708 */
709 static private void ERR(StringId err, StringId suberr, int CODE,
710 Object... subvalues) {
711 if (suberr == null)
712 System.err.println(trans(err));
713 else
714 System.err.println(trans(err, trans(suberr, subvalues)));
715
59597d59 716 System.err.flush();
88eb8122
NR
717 System.exit(CODE);
718 }
7da41ecd 719}