Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / extensions / extI18n / src / main / java / org / gvsig / i18n / impl / I18nManagerImpl.java @ 29635

History | View | Annotate | Download (23.1 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Gobernment (CIT)
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
 * MA  02110-1301, USA.
20
 * 
21
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 {DiSiD Technologies}  {New extension for installation and update of text translations}
26
 */
27
package org.gvsig.i18n.impl;
28

    
29
import java.io.BufferedReader;
30
import java.io.BufferedWriter;
31
import java.io.File;
32
import java.io.FileOutputStream;
33
import java.io.FileWriter;
34
import java.io.IOException;
35
import java.io.InputStream;
36
import java.io.InputStreamReader;
37
import java.io.OutputStreamWriter;
38
import java.io.PrintStream;
39
import java.security.AccessController;
40
import java.security.PrivilegedAction;
41
import java.util.ArrayList;
42
import java.util.HashMap;
43
import java.util.HashSet;
44
import java.util.Iterator;
45
import java.util.List;
46
import java.util.Locale;
47
import java.util.Map;
48
import java.util.Set;
49
import java.util.StringTokenizer;
50
import java.util.Map.Entry;
51
import java.util.zip.ZipEntry;
52
import java.util.zip.ZipFile;
53
import java.util.zip.ZipOutputStream;
54

    
55
import org.gvsig.andami.Launcher;
56
import org.gvsig.andami.PluginServices;
57
import org.gvsig.andami.config.generate.AndamiConfig;
58
import org.gvsig.i18n.I18nException;
59
import org.gvsig.i18n.I18nManager;
60
import org.gvsig.i18n.Messages;
61
import org.gvsig.utils.StringUtilities;
62
import org.gvsig.utils.XMLEntity;
63

    
64

    
65
/**
66
 * Implementation of the I18nManager interface.
67
 * 
68
 * @author <a href="mailto:dcervera@disid.com">David Cervera</a>
69
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
70
 */
71
public class I18nManagerImpl implements I18nManager {
72

    
73
        private static final String LOCALES_FILE_NAME = "locales.csv";
74

    
75
        private static final String CSV_SEPARATOR = ",";
76

    
77
        private static final String I18N_EXTENSION = "org.gvsig.i18n.extension";
78

    
79
        private static final String VARIANT = "variant";
80

    
81
        private static final String COUNTRY = "country";
82

    
83
        private static final String LANGUAGE = "language";
84

    
85
        private static final String REGISTERED_LOCALES_PERSISTENCE = "RegisteredLocales";
86

    
87
        private static final I18nManager DEFAULT = new I18nManagerImpl();
88

    
89
        private Set registeredLocales;
90

    
91
        /**
92
         * The list of default reference locales. The last one will be used to get
93
         * all the keys when translating to a new locale.
94
         */
95
        private Locale[] referenceLocales = new Locale[] { ENGLISH, SPANISH };
96

    
97
        private Locale[] defaultLocales = new Locale[] {
98
        // Default supported locales
99
                        new Locale("ca"), // Catalan
100
                        new Locale("cs"), // Czech
101
                        new Locale("de"), // German
102
                        ENGLISH, // English
103
                        SPANISH, // Spanish
104
                        new Locale("eu"), // Basque
105
                        new Locale("fr"), // French
106
                        new Locale("gl"), // Galician
107
                        new Locale("it"), // Italian
108
                        new Locale("pl"), // Polish
109
                        new Locale("pt"), // Portuguese
110
                        new Locale("ro"), // Romanian
111
                        new Locale("zh"), // Chinese
112
                        new Locale("ru"), // Russian
113
                        new Locale("el"), // Greek
114
                        new Locale("ro"), // Romanian
115
                        new Locale("pl"), // Polish
116
        };
117

    
118
        /**
119
         * Returns the unique instance of the I18nManager.
120
         * 
121
         * @return the unique instance
122
         */
123
        public static I18nManager getInstance() {
124
                return DEFAULT;
125
        }
126

    
127
        public static String capitalize(String text) {
128
                // Convert the first letter to uppercase
129
                String capitalLetter = new String(new char[] { Character
130
                                .toUpperCase(text.charAt(0)) });
131
                return capitalLetter.concat(text.substring(1));
132
        }
133

    
134
        /**
135
         * Empty constructor.
136
         */
137
        I18nManagerImpl() {
138
        }
139

    
140
        public Locale[] getInstalledLocales() {
141
                if (registeredLocales == null) {
142

    
143
                        XMLEntity child = getRegisteredLocalesPersistence();
144

    
145
                        // If the list of registered locales is not already persisted,
146
                        // this should be the first time gvSIG is run with the I18nPlugin
147
                        // so we will take the list of default locales
148
                        if (child == null) {
149
                                Locale[] defaultLocales = getDefaultLocales();
150
                                registeredLocales = new HashSet(defaultLocales.length);
151
                                for (int i = 0; i < defaultLocales.length; i++) {
152
                                        registeredLocales.add(defaultLocales[i]);
153
                                }
154
                                storeInstalledLocales();
155
                        } else {
156
                                XMLEntity localesEntity = getRegisteredLocalesPersistence();
157
                                registeredLocales = new HashSet(localesEntity
158
                                                .getChildrenCount());
159
                                for (int i = 0; i < localesEntity.getChildrenCount(); i++) {
160
                                        XMLEntity localeEntity = localesEntity.getChild(i);
161
                                        String language = localeEntity.getStringProperty(LANGUAGE);
162
                                        String country = localeEntity.getStringProperty(COUNTRY);
163
                                        String variant = localeEntity.getStringProperty(VARIANT);
164
                                        Locale locale = new Locale(language, country, variant);
165
                                        registeredLocales.add(locale);
166
                                }
167
                        }
168
                }
169

    
170
                return (Locale[]) registeredLocales
171
                                .toArray(new Locale[registeredLocales.size()]);
172
        }
173

    
174
        public void uninstallLocale(Locale locale) throws I18nException {
175
                if (getCurrentLocale().equals(locale) || isReferenceLocale(locale)) {
176
                        throw new UninstallLocaleException(locale);
177
                }
178

    
179
                if (registeredLocales.remove(locale)) {
180
                        // Remove from the configured locale list
181
                        storeInstalledLocales();
182

    
183
                        // Remove the resource bundle file
184
                        File bundleFile = new File(getResourcesFolder(),
185
                                        getResourceFileName(locale));
186

    
187
                        if (bundleFile.exists()) {
188
                                bundleFile.delete();
189
                        }
190
                }
191
        }
192

    
193
        public String getDisplayName(Locale locale) {
194
                return getDisplayName(locale, locale);
195
        }
196

    
197
        public String getDisplayName(Locale locale, Locale displayLocale) {
198
                StringBuffer name = new StringBuffer(getLanguageDisplayName(locale,
199
                                displayLocale));
200

    
201
                if (!isEmpty(locale.getCountry())) {
202
                        name.append(" - ");
203
                        name.append(locale.getDisplayCountry(displayLocale));
204
                }
205

    
206
                if (!isEmpty(locale.getVariant())) {
207
                        name.append(" - ");
208
                        name.append(locale.getDisplayVariant(displayLocale));
209
                }
210

    
211
                name.append(" (").append(locale.toString()).append(")");
212

    
213
                return name.toString();
214
        }
215

    
216
        private boolean isEmpty(String text) {
217
                return text == null || text.trim().length() == 0;
218
        }
219

    
220
        public String getLanguageDisplayName(Locale locale) {
221
                return getLanguageDisplayName(locale, locale);
222
        }
223

    
224
        public String getLanguageDisplayName(Locale locale, Locale displayLocale) {
225

    
226
                String displayName;
227

    
228
                // Correction for the Basque language display name,
229
                // show it in Basque, not in Spanish
230
                if ("eu".equals(locale.getLanguage())
231
                                && "vascuence".equals(locale.getDisplayLanguage())) {
232
                        displayName = "Euskera";
233
                }
234
                // Patch for Valencian/Catalan
235
                else if ("ca".equals(locale.getLanguage())) {
236
                        // displayName = Messages.getText("__valenciano");
237
                        // if ("__valenciano".equals(displayName)) {
238
                        // displayName = Messages.getText("__catalan");
239
                        // }
240
                        displayName = "Valenci?";
241
                } else {
242
                        displayName = locale.getDisplayLanguage(displayLocale);
243
                }
244

    
245
                return capitalize(displayName);
246
        }
247

    
248
        public Locale getCurrentLocale() {
249
                return Locale.getDefault();
250
        }
251

    
252
        public Locale getDefaultSystemLocale() {
253
                String language, region, country, variant;
254
                language = getSystemProperty("user.language", "en");
255
                // for compatibility, check for old user.region property
256
                region = getSystemProperty("user.region", null);
257

    
258
                if (region != null) {
259
                        // region can be of form country, country_variant, or _variant
260
                        int i = region.indexOf('_');
261
                        if (i >= 0) {
262
                                country = region.substring(0, i);
263
                                variant = region.substring(i + 1);
264
                        } else {
265
                                country = region;
266
                                variant = "";
267
                        }
268
                } else {
269
                        country = getSystemProperty("user.country", "");
270
                        variant = getSystemProperty("user.variant", "");
271
                }
272
                return new Locale(language, country, variant);
273
        }
274

    
275
        public void setCurrentLocale(Locale locale) {
276
                AndamiConfig config = Launcher.getAndamiConfig();
277
                config.setLocaleLanguage(locale.getLanguage());
278
                config.setLocaleCountry(locale.getCountry());
279
                config.setLocaleVariant(locale.getVariant());
280
        }
281

    
282
        public Locale[] installLocales(File importFile) throws I18nException {
283
                List importLocales = new ArrayList();
284

    
285
                try {
286
                        ZipFile zipFile = new ZipFile(importFile);
287

    
288
                        Map locales = getZipFileNonReferenceLocales(zipFile);
289

    
290
                        if (locales == null || locales.size() == 0) {
291
                                return null;
292
                        }
293

    
294
                        for (Iterator iterator = locales.entrySet().iterator(); iterator
295
                                        .hasNext();) {
296
                                Entry entry = (Entry) iterator.next();
297

    
298
                                String fileName = (String) entry.getKey();
299
                                Locale locale = (Locale) entry.getValue();
300
                                importLocales.add(locale);
301

    
302
                                // Add the locale to the list of installed ones, if it
303
                                // is new, otherwise, update the texts.
304
                                if (!registeredLocales.contains(locale)) {
305
                                        registeredLocales.add(locale);
306
                                        storeInstalledLocales();
307
                                }
308

    
309
                                // Replace the old bundle with the new one
310
                                ZipEntry zipEntry = zipFile.getEntry(fileName);
311
                                InputStream is = zipFile.getInputStream(zipEntry);
312
                                BufferedReader reader = new BufferedReader(
313
                                                new InputStreamReader(is));
314

    
315
                                File bundleFile = getResourceFile(locale);
316
                                FileWriter fileWriter = new FileWriter(bundleFile);
317
                                BufferedWriter writer = new BufferedWriter(fileWriter);
318

    
319
                                String line;
320
                                while ((line = reader.readLine()) != null) {
321
                                        writer.write(line);
322
                                        writer.write('\n');
323
                                }
324
                                writer.flush();
325
                                writer.close();
326
                                fileWriter.close();
327
                                reader.close();
328
                                is.close();
329
                        }
330

    
331
                } catch (Exception ex) {
332
                        throw new InstallLocalesException(importFile, ex);
333
                }
334

    
335
                return (Locale[]) importLocales
336
                                .toArray(new Locale[importLocales.size()]);
337
        }
338

    
339
        public void exportLocaleForUpdate(Locale locale, Locale referenceLocale,
340
                        File exportFile) throws I18nException {
341

    
342
                exportLocalesForUpdate(new Locale[] { locale }, referenceLocale,
343
                                exportFile);
344
        }
345

    
346
        public void exportLocalesForUpdate(Locale[] locales,
347
                        Locale referenceLocale, File exportFile) throws I18nException {
348

    
349
                exportLocale(locales, new Locale[] { referenceLocale }, exportFile,
350
                                true);
351
        }
352

    
353
        public void exportLocaleForTranslation(Locale locale,
354
                        Locale referenceLocale, File exportFile) throws I18nException {
355

    
356
                exportLocaleForTranslation(locale, new Locale[] { referenceLocale },
357
                                exportFile);
358
        }
359

    
360
        public void exportLocaleForTranslation(Locale locale,
361
                        Locale[] referenceLocales, File exportFile) throws I18nException {
362

    
363
                exportLocale(new Locale[] { locale }, referenceLocales, exportFile,
364
                                false);
365
        }
366

    
367
        public Locale[] getReferenceLocales() {
368
                return referenceLocales;
369
        }
370

    
371
        public void setReferenceLocales(Locale[] referenceLocales) {
372
                this.referenceLocales = referenceLocales;
373
        }
374

    
375
        public void setDefaultLocales(Locale[] defaultLocales) {
376
                this.defaultLocales = defaultLocales;
377
        }
378

    
379
        private void exportLocale(Locale[] locales, Locale[] referenceLocales,
380
                        File exportFile, boolean update) throws I18nException {
381

    
382
                Locale[] refArray = getReferenceLocalesToExport(locales,
383
                                referenceLocales);
384

    
385
                try {
386
                        FileOutputStream fos = new FileOutputStream(exportFile);
387
                        ZipOutputStream zipos = new ZipOutputStream(fos);
388

    
389
                        // Create the index file
390
                        writeZipFileLocales(zipos, locales, refArray);
391

    
392
                        PrintStream ps = new PrintStream(zipos);
393
                        Map texts = null;
394

    
395
                        if (update) {
396
                                // First, export the locales to update
397
                                if (locales != null) {
398
                                        for (int i = 0; i < locales.length; i++) {
399
                                                texts = getAllTexts(locales[i]);
400
                                                putResourceInZip(zipos, ps, texts,
401
                                                                getResourceFileName(locales[i]));
402
                                        }
403
                                }
404
                        } else { // translate
405
                                // First, export the locales to translate, taking the keys from
406
                                // the reference locales, but without values
407
                                // We will use the keys of the reference locales
408
                                texts = getAllTexts(referenceLocales[0]);
409
                                if (locales != null) {
410
                                        for (int i = 0; i < locales.length; i++) {
411
                                                putResourceInZip(zipos, ps, texts,
412
                                                                getResourceFileName(locales[i]), false);
413
                                        }
414
                                }
415
                        }
416

    
417
                        // Next, export the reference locales
418
                        if (refArray != null) {
419
                                for (int i = 0; i < refArray.length; i++) {
420
                                        texts = getAllTexts(refArray[i]);
421
                                        putResourceInZip(zipos, ps, texts,
422
                                                        getResourceFileName(refArray[i]));
423
                                }
424
                        }
425

    
426
                        ps.flush();
427
                        ps.close();
428
                        zipos.close();
429
                        fos.close();
430
                } catch (IOException ex) {
431
                        throw new ExportLocaleException(locales, ex);
432
                }
433
        }
434

    
435
        /**
436
         * Returns the list of reference locales to export, as the union of the
437
         * default reference locales list and the one selected as reference. The
438
         * locales to translate or update are extracted from the list.
439
         */
440
        private Locale[] getReferenceLocalesToExport(Locale[] locales,
441
                        Locale[] referenceLocalesSelected) {
442
                // The reference locales to export are the default ones plus the
443
                // selected by the user.
444
                Set exportRefLocales = new HashSet(referenceLocales.length);
445
                for (int i = 0; i < referenceLocales.length; i++) {
446
                        exportRefLocales.add(referenceLocales[i]);
447
                }
448
                if (referenceLocalesSelected != null) {
449
                        for (int i = 0; i < referenceLocalesSelected.length; i++) {
450
                                exportRefLocales.add(referenceLocalesSelected[i]);
451
                        }
452
                }
453
                if (locales != null) {
454
                        for (int i = 0; i < locales.length; i++) {
455
                                exportRefLocales.remove(locales[i]);
456
                        }
457
                }
458
                Locale[] refArray = (Locale[]) exportRefLocales
459
                                .toArray(new Locale[exportRefLocales.size()]);
460
                return refArray;
461
        }
462

    
463
        /**
464
         * Returns all the localized texts and its keys for a locale.
465
         */
466
        private Map getAllTexts(Locale locale) {
467
                return Messages.getAllTexts(locale);
468
        }
469

    
470
        private Map getZipFileNonReferenceLocales(ZipFile zipFile)
471
                        throws I18nException {
472
                ZipEntry zipEntry = zipFile.getEntry(LOCALES_FILE_NAME);
473

    
474
                if (zipEntry == null) {
475
                        return null;
476
                }
477

    
478
                Map locales;
479
                try {
480
                        InputStream is = zipFile.getInputStream(zipEntry);
481
                        BufferedReader reader = new BufferedReader(
482
                                        new InputStreamReader(is));
483

    
484
                        locales = new HashMap(2);
485
                        String line;
486
                        while ((line = reader.readLine()) != null) {
487
                                // The excepted format is:
488
                                // FILENAME,LANGUAGE,COUNTRY,VARIANT,IS_REFERENCE
489
                                StringTokenizer st = new StringTokenizer(line, CSV_SEPARATOR,
490
                                                true);
491
                                // First: locale file name (required)
492
                                String fileName = st.nextToken();
493
                                if (CSV_SEPARATOR.equals(fileName)) {
494
                                        throw new LocaleFileNameRequiredException(line);
495
                                } else {
496
                                        // Read the next separator
497
                                        st.nextToken();
498
                                }
499
                                // Second: the locale language (required)
500
                                String language = st.nextToken();
501
                                if (CSV_SEPARATOR.equals(language)) {
502
                                        throw new LocaleLanguageRequiredException(line);
503
                                } else {
504
                                        // Read the next separator
505
                                        st.nextToken();
506
                                }
507
                                // Third: the country
508
                                String country = st.nextToken();
509
                                if (CSV_SEPARATOR.equals(country)) {
510
                                        country = null;
511
                                } else {
512
                                        // Read the next separator
513
                                        st.nextToken();
514
                                }
515
                                // Fourth: the variant
516
                                String variant = st.nextToken();
517
                                if (CSV_SEPARATOR.equals(variant)) {
518
                                        variant = null;
519
                                } else {
520
                                        // Read the next separator
521
                                        st.nextToken();
522
                                }
523
                                // Fifth: is a reference locale?
524
                                String refStr = st.nextToken();
525
                                if (CSV_SEPARATOR.equals(refStr)) {
526
                                        refStr = null;
527
                                }
528

    
529
                                // Only add non reference locales
530
                                if (refStr != null && !"true".equals(refStr.toLowerCase())) {
531
                                        // Variant only accepted if country defined
532
                                        if (country == null) {
533
                                                variant = null;
534
                                        }
535
                                        country = country == null ? "" : country;
536
                                        variant = variant == null ? "" : variant;
537
                                        Locale locale = new Locale(language, country, variant);
538

    
539
                                        locales.put(fileName, locale);
540
                                }
541
                        }
542

    
543
                        reader.close();
544
                        is.close();
545
                } catch (IOException ex) {
546
                        throw new ReadCSVLocalesFileException(ex);
547
                }
548

    
549
                return locales;
550
        }
551

    
552
        private void writeZipFileLocales(ZipOutputStream zos, Locale[] locales,
553
                        Locale[] referenceLocales) throws IOException {
554
                ZipEntry zipEntry = new ZipEntry(LOCALES_FILE_NAME);
555

    
556
                zos.putNextEntry(zipEntry);
557
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(zos));
558

    
559
                if (locales != null) {
560
                        for (int i = 0; i < locales.length; i++) {
561
                                writeLocaleEntry(locales[i], writer, false);
562
                        }
563
                }
564
                if (referenceLocales != null) {
565
                        for (int i = 0; i < referenceLocales.length; i++) {
566
                                writeLocaleEntry(referenceLocales[i], writer, true);
567
                        }
568
                }
569

    
570
                writer.flush();
571
                zos.closeEntry();
572
        }
573

    
574
        /**
575
         * Writes the locale entry into a writer.
576
         * 
577
         * @param locale
578
         *            the locale to create the entry for
579
         * @param writer
580
         *            to write to
581
         * @param reference
582
         *            is it is a reference locale or not
583
         * @throws IOException
584
         *             if there is an error creating the locale entry
585
         */
586
        private void writeLocaleEntry(Locale locale, BufferedWriter writer,
587
                        boolean reference) throws IOException {
588
                String language = locale.getLanguage();
589
                String country = locale.getCountry();
590
                country = country == null ? "" : country;
591
                String variant = locale.getVariant();
592
                variant = variant == null ? "" : variant;
593

    
594
                writer.write(getResourceFileName(locale));
595
                writer.write(',');
596
                writer.write(language);
597
                writer.write(',');
598
                writer.write(country);
599
                writer.write(',');
600
                writer.write(variant);
601
                writer.write(',');
602
                writer.write(Boolean.toString(reference));
603
                writer.write('\n');
604
        }
605

    
606
        /**
607
         * Returns if a locale is one of the default reference ones.
608
         */
609
        private boolean isReferenceLocale(Locale locale) {
610
                for (int i = 0; i < referenceLocales.length; i++) {
611
                        if (referenceLocales[i].equals(locale)) {
612
                                return true;
613
                        }
614
                }
615
                return false;
616
        }
617

    
618
        /**
619
         * Puts a new resource file into a Jar file.
620
         */
621
        private void putResourceInZip(ZipOutputStream zipos, PrintStream ps,
622
                        Map texts, String resourceFileName) throws IOException {
623

    
624
                putResourceInZip(zipos, ps, texts, resourceFileName, true);
625
        }
626

    
627
        /**
628
         * Puts a new resource file into a Jar file.
629
         */
630
        private void putResourceInZip(ZipOutputStream zipos, PrintStream ps,
631
                        Map texts, String resourceFileName, boolean withValue)
632
                        throws IOException {
633
                // Add ZIP entry for the resource bundle file
634
                zipos.putNextEntry(new ZipEntry(resourceFileName));
635

    
636
                for (Iterator iterator = texts.entrySet().iterator(); iterator
637
                                .hasNext();) {
638
                        Entry entry = (Entry) iterator.next();
639
                        String keyEncoded = escape((String) entry.getKey(), true);
640
                        ps.print(keyEncoded);
641
                        ps.print("=");
642
                        if (withValue) {
643
                                String valueEncoded = escape((String) entry.getValue(), false);
644
                                ps.println(valueEncoded);
645
                        } else {
646
                                ps.println();
647
                        }
648
                }
649

    
650
                ps.flush();
651

    
652
                // Close the ZIP entry, the file is complete
653
                zipos.closeEntry();
654
        }
655

    
656
        /**
657
         * Returns the file which contains the translations for a locale.
658
         */
659
        private File getResourceFile(Locale locale) {
660
                return new File(getResourcesFolder(), getResourceFileName(locale));
661
        }
662

    
663
        /**
664
         * Returns the name of the file which contains the translations for a
665
         * locale.
666
         */
667
        private String getResourceFileName(Locale locale) {
668
                StringBuffer fileName = new StringBuffer("text");
669

    
670
                // Spanish without country is the default locale
671
                if (!(isEmpty(locale.getCountry()) && "es".equals(locale.getLanguage()))) {
672
                        fileName.append('_').append(locale.getLanguage());
673
                }
674

    
675
                // Add the locale country
676
                if (!isEmpty(locale.getCountry())) {
677
                        fileName.append('_').append(locale.getCountry());
678
                }
679

    
680
                // Add the locale variant
681
                if (!isEmpty(locale.getVariant())) {
682
                        fileName.append('_').append(locale.getVariant());
683
                }
684

    
685
                fileName.append(".properties");
686
                return fileName.toString();
687
        }
688

    
689
        /**
690
         * Returns the folder where to store the resource bundle files.
691
         */
692
        private File getResourcesFolder() {
693
                return PluginServices.getPluginServices("com.iver.cit.gvsig")
694
                                .getPluginDirectory();
695
        }
696

    
697
        /**
698
         * Returns the child XMLEntity with the RegisteredLocales.
699
         */
700
        private XMLEntity getRegisteredLocalesPersistence() {
701
                XMLEntity entity = getI18nPersistence();
702
                XMLEntity child = null;
703
                for (int i = entity.getChildrenCount() - 1; i >= 0; i--) {
704
                        XMLEntity tmpchild = entity.getChild(i);
705
                        if (tmpchild.getName().equals(REGISTERED_LOCALES_PERSISTENCE)) {
706
                                child = tmpchild;
707
                                break;
708
                        }
709
                }
710
                return child;
711
        }
712

    
713
        /**
714
         * Returns the I18n Plugin persistence.
715
         */
716
        private XMLEntity getI18nPersistence() {
717
                XMLEntity entity = PluginServices.getPluginServices(I18N_EXTENSION)
718
                                .getPersistentXML();
719
                return entity;
720
        }
721

    
722
        /**
723
         * Returns the list of default locales bundled with gvSIG.
724
         */
725
        private Locale[] getDefaultLocales() {
726
                return defaultLocales;
727
        }
728

    
729
        /**
730
         * Stores the list of installed locales into the plugin persistence.
731
         */
732
        private void storeInstalledLocales() {
733
                XMLEntity localesEntity = getRegisteredLocalesPersistence();
734

    
735
                // Remove the previous list of registered languages
736
                if (localesEntity != null) {
737
                        XMLEntity i18nPersistence = getI18nPersistence();
738
                        for (int i = i18nPersistence.getChildrenCount() - 1; i >= 0; i--) {
739
                                XMLEntity child = i18nPersistence.getChild(i);
740
                                if (child.getName().equals(REGISTERED_LOCALES_PERSISTENCE)) {
741
                                        i18nPersistence.removeChild(i);
742
                                        break;
743
                                }
744
                        }
745
                }
746

    
747
                // Create the new persistence for the registered languages
748
                localesEntity = new XMLEntity();
749

    
750
                localesEntity.setName(REGISTERED_LOCALES_PERSISTENCE);
751

    
752
                for (Iterator iterator = registeredLocales.iterator(); iterator
753
                                .hasNext();) {
754
                        Locale locale = (Locale) iterator.next();
755
                        XMLEntity localeEntity = new XMLEntity();
756
                        localeEntity.setName(locale.getDisplayName());
757
                        localeEntity.putProperty(LANGUAGE, locale.getLanguage());
758
                        localeEntity.putProperty(COUNTRY, locale.getCountry());
759
                        localeEntity.putProperty(VARIANT, locale.getVariant());
760

    
761
                        localesEntity.addChild(localeEntity);
762
                }
763

    
764
                getI18nPersistence().addChild(localesEntity);
765
        }
766

    
767
        private String escape(String value, boolean replaceBlanks) {
768
                // First replace non printable characters
769
                if (replaceBlanks) {
770
                        value = StringUtilities.replace(value, " ", "\\ ");
771
                }
772
                value = StringUtilities.replace(value, ":", "\\:");
773
                value = StringUtilities.replace(value, "\n", "\\n");
774
                value = StringUtilities.replace(value, "\t", "\\t");
775
                value = StringUtilities.replace(value, "\b", "\\b");
776
                value = StringUtilities.replace(value, "\f", "\\f");
777
                value = StringUtilities.replace(value, "\r", "\\r");
778
                // value = StringUtilities.replace(value, "\\", "\\\\");
779
                // value = StringUtilities.replace(value, "\'", "\\\'");
780
                // value = StringUtilities.replace(value, "\"", "\\\"");
781

    
782
                // Next, encode in raw-unicode-escape
783
                return toRawUnicodeEncoded(value);
784
        }
785

    
786
        private String toRawUnicodeEncoded(String value) {
787
                StringBuffer sb = new StringBuffer();
788
                for (int i = 0; i < value.length(); i++) {
789
                        char c = value.charAt(i);
790
                        if (c <= 0x80) {
791
                                sb.append(c);
792
                        } else {
793
                                sb.append("\\u");
794
                                String hexValue = Integer.toHexString((int) c);
795
                                // Append 0 if the hex value has less than 4 digits
796
                                for (int j = hexValue.length(); j < 4; j++) {
797
                                        sb.append('0');
798
                                }
799
                                sb.append(hexValue);
800
                        }
801
                }
802
                return sb.toString();
803
        }
804
        
805
        @SuppressWarnings("unchecked")
806
        private String getSystemProperty(final String property, String defaultValue) {
807
                String value = (String) AccessController
808
                .doPrivileged(new PrivilegedAction() {
809
                        public Object run() {
810
                                return System.getProperty(property);
811
                        }
812
                });                
813
                return value == null ? defaultValue : value;
814
        }
815
}