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