001: /**
002: * Caption: Zaval Java Resource Editor
003: * $Revision: 0.37 $
004: * $Date: 2002/03/28 9:24:42 $
005: *
006: * @author: Victor Krapivin
007: * @version: 1.0
008: *
009: * Zaval JRC Editor is a visual editor which allows you to manipulate
010: * localization strings for all Java based software with appropriate
011: * support embedded.
012: *
013: * For more info on this product read Zaval Java Resource Editor User's Guide
014: * (It comes within this package).
015: * The latest product version is always available from the product's homepage:
016: * http://www.zaval.org/products/jrc-editor/
017: * and from the SourceForge:
018: * http://sourceforge.net/projects/zaval0002/
019: *
020: * Contacts:
021: * Support : support@zaval.org
022: * Change Requests : change-request@zaval.org
023: * Feedback : feedback@zaval.org
024: * Other : info@zaval.org
025: *
026: * Copyright (C) 2001-2002 Zaval Creative Engineering Group (http://www.zaval.org)
027: *
028: * This program is free software; you can redistribute it and/or
029: * modify it under the terms of the GNU General Public License
030: * (version 2) as published by the Free Software Foundation.
031: *
032: * This program is distributed in the hope that it will be useful,
033: * but WITHOUT ANY WARRANTY; without even the implied warranty of
034: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
035: * GNU General Public License for more details.
036: *
037: * You should have received a copy of the GNU General Public License
038: * along with this program; if not, write to the Free Software
039: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
040: *
041: */package org.zaval.tools.i18n.translator;
042:
043: import java.io.*;
044: import java.awt.*;
045: import java.util.*;
046:
047: import org.zaval.util.SafeResourceBundle;
048:
049: class BundleManager implements TranslatorConstants {
050: private BundleSet set;
051:
052: BundleManager() {
053: set = new BundleSet();
054: }
055:
056: void appendResource(InputStream stream, String lang)
057: throws IOException {
058: readResource(stream, lang);
059: }
060:
061: BundleManager(String baseFileName) throws IOException {
062: set = new BundleSet();
063: readResources(baseFileName);
064: }
065:
066: BundleSet getBundle() {
067: return set;
068: }
069:
070: String dirName(String fn) {
071: fn = replace(fn, "\\", "/");
072: int ind = fn.lastIndexOf('/');
073: return ind >= 0 ? fn.substring(0, ind + 1) : "./";
074: }
075:
076: String baseName(String fn) {
077: fn = replace(fn, "\\", "/");
078: int ind = fn.lastIndexOf('/');
079: fn = ind >= 0 ? fn.substring(ind + 1) : fn;
080: ind = fn.lastIndexOf('.');
081: return ind >= 0 ? fn.substring(0, ind) : fn;
082: }
083:
084: private String extName(String fn) {
085: fn = replace(fn, "\\", "/");
086: int ind = fn.lastIndexOf('.');
087: return ind >= 0 ? fn.substring(ind) : "";
088: }
089:
090: private String purifyFileName(String fn) {
091: fn = baseName(fn);
092: int ind = fn.lastIndexOf('_');
093: int in2 = ind > 0 ? fn.lastIndexOf('_', ind - 1) : -1;
094: if (in2 < 0 && ind > 0)
095: in2 = ind;
096: return in2 >= 0 ? fn.substring(0, in2) : fn;
097: }
098:
099: private Vector getResFiles(String dir, String baseFileName,
100: String defExt) {
101: File f = new File(dir);
102: String bpn = purifyFileName(baseFileName);
103: String[] fs = f.list();
104: if (fs.length == 0)
105: return null;
106: Vector res = new Vector();
107: for (int i = 0; i < fs.length; ++i) {
108: if (!fs[i].startsWith(bpn))
109: continue;
110: String bfn = purifyFileName(fs[i]);
111: if (!bfn.equals(bpn))
112: continue;
113: if (!extName(fs[i]).equals(defExt))
114: continue;
115: File f2 = new File(dir + fs[i]);
116: if (!f2.isDirectory())
117: res.addElement(fs[i]);
118: }
119: return res;
120: }
121:
122: String determineLanguage(String fn) {
123: fn = baseName(fn);
124: int ind = fn.lastIndexOf('_');
125: int in2 = ind > 0 ? fn.lastIndexOf('_', ind - 1) : -1;
126: if (in2 < 0 && ind > 0)
127: in2 = ind;
128: return in2 >= 0 ? fn.substring(in2 + 1) : "en";
129: }
130:
131: private void readResources(String baseFileName) throws IOException {
132: String dir = dirName(baseFileName);
133: String ext = extName(baseFileName);
134: baseFileName = baseName(baseFileName);
135:
136: Vector fileNames = getResFiles(dir, baseFileName, ext);
137: for (int i = 0; i < fileNames.size(); i++) {
138: String fn = (String) fileNames.elementAt(i);
139: // long t1 = System.currentTimeMillis();
140: readResource(dir + fn, determineLanguage(fn));
141: // long t2 = System.currentTimeMillis();
142: // System.err.println(" ... ["+determineLanguage(fn)+"]: " + (t2 - t1) + "ms");
143: }
144: }
145:
146: private void readResource(String fullName, String lang)
147: throws IOException {
148: // long t1 = System.currentTimeMillis();
149: Vector lines = getLines(fullName);
150: // long t2 = System.currentTimeMillis();
151: proceedLines(lines, lang, fullName);
152: // long t3 = System.currentTimeMillis();
153: // System.err.println(" ... read stream = " + (t2 - t1) + "ms");
154: // System.err.println(" ... parse lines = " + (t3 - t2) + "ms");
155: }
156:
157: private void readResource(InputStream in, String lang)
158: throws IOException {
159: Vector lines = getLines(in);
160: proceedLines(lines, lang, null);
161: }
162:
163: private void proceedLines(Vector lines, String lang, String fullName) {
164: String lastComment = null;
165: fullName = fullName != null ? fullName : "tmp_" + lang;
166: set.addLanguage(lang);
167: set.getLanguage(lang).setLangFile(fullName);
168: for (int i = 0; i < lines.size(); i++) {
169: String line = (String) lines.elementAt(i);
170: line = line.trim();
171: if (line.length() == 0)
172: continue;
173: if (line.startsWith("#")) {
174: lastComment = line.substring(1);
175: continue;
176: }
177: int q = line.indexOf('#');
178: // if(q>0) line = line.substring(0, q).trim();
179:
180: StringTokenizer st = new StringTokenizer(line, "=", true); // key = value
181: if (st.countTokens() < 2)
182: continue; // syntax error, ignored
183: String dname = st.nextToken().trim();
184: st.nextToken(); // '='
185: String value = "";
186: if (st.hasMoreTokens())
187: value = st.nextToken("");
188:
189: BundleItem bi = set.getItem(dname);
190: if (bi == null)
191: bi = set.addKey(dname);
192: bi.setTranslation(lang, value);
193: bi.setComment(lastComment);
194: lastComment = null;
195: }
196: set.resort();
197: }
198:
199: void setComment(String key, String comment) {
200: BundleItem bi = set.getItem(key);
201: if (bi == null)
202: return;
203: bi.setComment(comment);
204: }
205:
206: private Vector getLines(String fileName) throws IOException {
207: Vector res = new Vector();
208: if (fileName.endsWith(RES_EXTENSION)) {
209: DataInputStream in = new DataInputStream(
210: new FileInputStream(fileName));
211: String line = null;
212: while ((line = in.readLine()) != null) {
213: for (;;) {
214: line = line.trim();
215: if (line.endsWith("\\")) {
216: String line2 = in.readLine();
217: if (line2 != null)
218: line = line.substring(0, line.length() - 1)
219: + line2;
220: else
221: break;
222: } else
223: break;
224: }
225: res.addElement(fromEscape(line));
226: }
227: in.close();
228: } else {
229: RandomAccessFile in = new RandomAccessFile(fileName, "r");
230: StringBuffer sb = new StringBuffer();
231: int factor1 = 1;
232: int factor2 = 256;
233: for (;;) {
234: if (in.length() - in.getFilePointer() == 0)
235: break;
236: int i = in.readUnsignedByte() * factor1
237: + in.readUnsignedByte() * factor2;
238: if (i == 0xFFFE) {
239: factor1 = 256;
240: factor2 = 1;
241: }
242: if (i != 0x0D && i != 0xFFFE && i != 0xFEFF
243: && i != 0xFFFF)
244: if (i != 0x0A)
245: sb.append((char) i);
246: else {
247: res.addElement(fromEscape(sb.toString()));
248: sb.setLength(0);
249: }
250: }
251: in.close();
252: }
253: return res;
254: }
255:
256: private Vector getLines(InputStream xin) throws IOException {
257: Vector res = new Vector();
258: DataInputStream in = new DataInputStream(xin);
259: String line = null;
260: while ((line = in.readLine()) != null) {
261: for (;;) {
262: line = line.trim();
263: if (line.endsWith("\\")) {
264: String line2 = in.readLine();
265: if (line2 != null)
266: line = line.substring(0, line.length() - 1)
267: + line2;
268: else
269: break;
270: } else
271: break;
272: }
273: res.addElement(fromEscape(line));
274: }
275: in.close();
276: return res;
277: }
278:
279: private static String toEscape(String s) {
280: StringBuffer res = new StringBuffer();
281: for (int i = 0; i < s.length(); i++) {
282: char ch = s.charAt(i);
283: int val = (int) ch;
284: if (ch == '\r')
285: continue;
286: if (val >= 0 && val < 128 && ch != '\n' && ch != '\\')
287: res.append(ch);
288: else {
289: res.append("\\u");
290: String hex = Integer.toHexString(val);
291: for (int j = 0; j < 4 - hex.length(); j++)
292: res.append("0");
293: res.append(hex);
294: }
295: }
296: return res.toString();
297: }
298:
299: private static String fromEscape(String s) {
300: StringBuffer res = new StringBuffer(s.length());
301: for (int i = 0; i < s.length(); i++) {
302: char ch = s.charAt(i);
303: if (ch == '\\' && i + 1 >= s.length()) {
304: res.append(ch);
305: break;
306: }
307: if (ch != '\\')
308: res.append(ch);
309: else {
310: switch (s.charAt(i + 1)) {
311: case 'u':
312: res.append((char) Integer.parseInt(s.substring(
313: i + 2, i + 6), 16));
314: i += 5;
315: break;
316: case 'n':
317: res.append('\n');
318: i++;
319: break;
320: case 't':
321: res.append('\t');
322: i++;
323: break;
324: case 'r':
325: res.append('\r');
326: i++;
327: break;
328: default:
329: break;
330: }
331: }
332: }
333: return res.toString();
334: }
335:
336: String replace(String line, String from, String to) {
337: StringBuffer res = new StringBuffer(line.length());
338: String tmpstr;
339: int ind = -1, lastind = 0;
340:
341: while ((ind = line.indexOf(from, ind + 1)) != -1) {
342: if (lastind < ind) {
343: tmpstr = line.substring(lastind, ind);
344: res.append(tmpstr);
345: }
346: res.append(to);
347: lastind = ind + from.length();
348: ind += from.length() - 1;
349: }
350: if (lastind == 0)
351: return line;
352: res.append(line.substring(lastind));
353: return res.toString();
354: }
355:
356: void store(String fileName) throws IOException {
357: int j, k = set.getLangCount();
358: for (j = 0; j < k; ++j) {
359: LangItem lang = set.getLanguage(j);
360: store(lang.getLangId(), fileName);
361: }
362: }
363:
364: void store(String lng, String fn) throws IOException {
365: LangItem lang = set.getLanguage(lng);
366: if (fn == null)
367: fn = lang.getLangFile();
368: else {
369: String tmpFn = fn;
370: tmpFn = dirName(tmpFn) + purifyFileName(tmpFn);
371: if (set.getLanguage(0) != lang)
372: tmpFn += "_" + lang.getLangId();
373: tmpFn += RES_EXTENSION;
374: fn = tmpFn;
375: lang.setLangFile(fn);
376: }
377:
378: if (fn == null) {
379: store(lng, "autosaved.properties");
380: return;
381: }
382:
383: Vector lines = set.store(lang.getLangId());
384: if (fn.endsWith(RES_EXTENSION)) {
385: PrintStream f = new PrintStream(new FileOutputStream(fn));
386: for (int j = 0; j < lines.size(); j++)
387: f.print(toEscape((String) lines.elementAt(j))
388: + System.getProperty("line.separator"));
389: f.close();
390: } else {
391: FileOutputStream f = new FileOutputStream(fn);
392: f.write(0xFF);
393: f.write(0xFE);
394: for (int j = 0; j < lines.size(); j++) {
395: String s = (String) lines.elementAt(j);
396: s = replace(s, "\n", toEscape("\n"));
397: for (int k = 0; k < s.length(); k++) {
398: char ch = s.charAt(k);
399: f.write(((int) ch) & 255);
400: f.write(((int) ch) >> 8);
401: }
402: f.write(0x0D);
403: f.write(0x00);
404: f.write(0x0A);
405: f.write(0x00);
406: }
407: f.close();
408: }
409: }
410: }
|