Imported Upstream version 0.19.7
[platform/upstream/gettext.git] / gettext-tools / src / gnu / gettext / DumpResource.java
1 /* GNU gettext for Java
2  * Copyright (C) 2001-2003, 2007, 2015 Free Software Foundation, Inc.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package gnu.gettext;
19
20 import java.lang.reflect.*;
21 import java.util.*;
22 import java.io.*;
23
24 /**
25  * This programs dumps a resource as a PO file. The resource must be
26  * accessible through the CLASSPATH.
27  *
28  * @author Bruno Haible
29  */
30 public class DumpResource {
31   private Writer out;
32   private void dumpString (String str) throws IOException {
33     int n = str.length();
34     out.write('"');
35     for (int i = 0; i < n; i++) {
36       char c = str.charAt(i);
37       if (c == 0x0008) {
38         out.write('\\'); out.write('b');
39       } else if (c == 0x000c) {
40         out.write('\\'); out.write('f');
41       } else if (c == 0x000a) {
42         out.write('\\'); out.write('n');
43       } else if (c == 0x000d) {
44         out.write('\\'); out.write('r');
45       } else if (c == 0x0009) {
46         out.write('\\'); out.write('t');
47       } else if (c == '\\' || c == '"') {
48         out.write('\\'); out.write(c);
49       } else
50         out.write(c);
51     }
52     out.write('"');
53   }
54   private void dumpMessage (String msgid, String msgid_plural, Object msgstr) throws IOException {
55     int separatorPos = msgid.indexOf('\u0004');
56     if (separatorPos >= 0) {
57       String msgctxt = msgid.substring(0,separatorPos);
58       msgid = msgid.substring(separatorPos+1);
59       out.write("msgctxt "); dumpString(msgctxt);
60     }
61     out.write("msgid "); dumpString(msgid); out.write('\n');
62     if (msgid_plural != null) {
63       out.write("msgid_plural "); dumpString(msgid_plural); out.write('\n');
64       for (int i = 0; i < ((String[])msgstr).length; i++) {
65         out.write("msgstr[" + i + "] ");
66         dumpString(((String[])msgstr)[i]);
67         out.write('\n');
68       }
69     } else {
70       out.write("msgstr "); dumpString((String)msgstr); out.write('\n');
71     }
72     out.write('\n');
73   }
74   private ResourceBundle catalog;
75   private Method lookupMethod;
76   // Lookup the value corresponding to a key found in catalog.getKeys().
77   // Here we assume that the catalog returns a non-inherited value for
78   // these keys. FIXME: Not true. Better see whether handleGetObject is
79   // public - it is in ListResourceBundle and PropertyResourceBundle.
80   private Object lookup (String key) {
81     Object value = null;
82     if (lookupMethod != null) {
83       try {
84         value = lookupMethod.invoke(catalog, new Object[] { key });
85       } catch (IllegalAccessException e) {
86         e.printStackTrace();
87       } catch (InvocationTargetException e) {
88         e.getTargetException().printStackTrace();
89       }
90     } else {
91       try {
92         value = catalog.getObject(key);
93       } catch (MissingResourceException e) {
94       }
95     }
96     return value;
97   }
98   private void dump () throws IOException {
99     lookupMethod = null;
100     try {
101       lookupMethod = catalog.getClass().getMethod("lookup", new Class[] { java.lang.String.class });
102     } catch (NoSuchMethodException e) {
103     } catch (SecurityException e) {
104     }
105     Method pluralMethod = null;
106     try {
107       pluralMethod = catalog.getClass().getMethod("get_msgid_plural_table", new Class[0]);
108     } catch (NoSuchMethodException e) {
109     } catch (SecurityException e) {
110     }
111     Field pluralField = null;
112     try {
113       pluralField = catalog.getClass().getField("plural");
114     } catch (NoSuchFieldException e) {
115     } catch (SecurityException e) {
116     }
117     // Search for the header entry.
118     {
119       Object header_entry = null;
120       Enumeration keys = catalog.getKeys();
121       while (keys.hasMoreElements())
122         if ("".equals(keys.nextElement())) {
123           header_entry = lookup("");
124           break;
125         }
126       // If there is no header entry, fake one.
127       // FIXME: This is not needed; right after po_lex_charset_init set
128       // the PO charset to UTF-8.
129       if (header_entry == null)
130         header_entry = "Content-Type: text/plain; charset=UTF-8\n";
131       dumpMessage("",null,header_entry);
132     }
133     // Now the other messages.
134     {
135       Enumeration keys = catalog.getKeys();
136       Object plural = null;
137       if (pluralMethod != null) {
138         // msgfmt versions > 0.13.1 create a static get_msgid_plural_table()
139         // method.
140         try {
141           plural = pluralMethod.invoke(catalog, new Object[0]);
142         } catch (IllegalAccessException e) {
143           e.printStackTrace();
144         } catch (InvocationTargetException e) {
145           e.getTargetException().printStackTrace();
146         }
147       } else if (pluralField != null) {
148         // msgfmt versions <= 0.13.1 create a static plural field.
149         try {
150           plural = pluralField.get(catalog);
151         } catch (IllegalAccessException e) {
152           e.printStackTrace();
153         }
154       }
155       if (plural instanceof String[]) {
156         // A GNU gettext created class with plural handling, Java2 format.
157         int i = 0;
158         while (keys.hasMoreElements()) {
159           String key = (String)keys.nextElement();
160           Object value = lookup(key);
161           String key_plural = (value instanceof String[] ? ((String[])plural)[i++] : null);
162           if (!"".equals(key))
163             dumpMessage(key,key_plural,value);
164         }
165         if (i != ((String[])plural).length)
166           throw new RuntimeException("wrong plural field length");
167       } else if (plural instanceof Hashtable) {
168         // A GNU gettext created class with plural handling, Java format.
169         while (keys.hasMoreElements()) {
170           String key = (String)keys.nextElement();
171           if (!"".equals(key)) {
172             Object value = lookup(key);
173             String key_plural = (value instanceof String[] ? (String)((Hashtable)plural).get(key) : null);
174             dumpMessage(key,key_plural,value);
175           }
176         }
177       } else if (plural == null) {
178         // No plural handling.
179         while (keys.hasMoreElements()) {
180           String key = (String)keys.nextElement();
181           if (!"".equals(key))
182             dumpMessage(key,null,lookup(key));
183         }
184       } else
185         throw new RuntimeException("wrong plural field value");
186     }
187   }
188
189   public DumpResource (String resource_name, String locale_name) {
190     // Split locale_name into language_country_variant.
191     String language;
192     String country;
193     String variant;
194     language = locale_name;
195     {
196       int i = language.indexOf('_');
197       if (i >= 0) {
198         country = language.substring(i+1);
199         language = language.substring(0,i);
200       } else
201         country = "";
202     }
203     {
204       int j = country.indexOf('_');
205       if (j >= 0) {
206         variant = country.substring(j+1);
207         country = country.substring(0,j);
208       } else
209         variant = "";
210     }
211     Locale locale = new Locale(language,country,variant);
212     // Get the resource.
213     ResourceBundle catalog = ResourceBundle.getBundle(resource_name,locale);
214     // We are only interested in the messsages belonging to the locale
215     // itself, not in the inherited messages. But catalog.getLocale() exists
216     // only in Java2 and sometimes differs from the given locale.
217     try {
218       Writer w1 = new OutputStreamWriter(System.out,"UTF8");
219       Writer w2 = new BufferedWriter(w1);
220       this.out = w2;
221       this.catalog = catalog;
222       dump();
223       w2.close();
224       w1.close();
225       System.out.flush();
226     } catch (IOException e) {
227       e.printStackTrace();
228       System.exit(1);
229     }
230   }
231
232   public static void main (String[] args) {
233     new DumpResource(args[0], args.length > 1 ? args[1] : "");
234     System.exit(0);
235   }
236 }