1 20 package org.enhydra.barracuda.taskdefs; 21 22 import java.util.*; 23 import java.io.*; 24 import org.apache.tools.ant.*; 25 import org.apache.tools.ant.taskdefs.*; 26 import org.apache.tools.ant.types.*; 27 import org.enhydra.xml.xmlc.taskdef.*; 28 29 45 public class Localize extends Xmlc { 46 47 private static String sep = System.getProperty("line.separator"); 48 49 static { 50 if (null==System.getProperty(XmlcUtils.DEFAULT_UTILS_CLASS_KEY)) { 53 System.setProperty(XmlcUtils.DEFAULT_UTILS_CLASS_KEY, LocalizeXmlcUtilsImpl.class.getName()); 54 } 55 } 56 57 protected boolean tidy = true; 60 61 public String masterFile=null; public String masterDir=null; 66 public final static String [] countryCodes = new String [] { 67 "aa", "ab", "af", "am", "ar", "as", "ay", "az", "ba", "be", "bg", "bh", 68 "bi", "bn", "bo", "br", "ca", "co", "cs", "cy", "da", "de", "dz", "el", 69 "en", "eo", "es", "et", "eu", "fa", "fi", "fj", "fo", "fr", "fy", "ga", 70 "gd", "gl", "gn", "gu", "ha", "he", "hi", "hr", "hu", "hy", "ia", "id", 71 "ie", "ik", "is", "it", "iu", "ja", "jw", "ka", "kk", "kl", "km", "kn", 72 "ko", "ks", "ku", "ky", "la", "ln", "lo", "lt", "lv", "mg", "mi", "mk", 73 "ml", "mn", "mo", "mr", "ms", "mt", "my", "na", "ne", "nl", "no", "oc", 74 "om", "or", "pa", "pl", "ps", "pt", "qu", "rm", "rn", "ro", "ru", "rw", 75 "sa", "sd", "sg", "sh", "si", "sk", "sl", "sm", "sn", "so", "sq", "sr", 76 "ss", "st", "su", "sv", "sw", "ta", "te", "tg", "th", "ti", "tk", "tl", 77 "tn", "to", "tr", "ts", "tt", "tw", "ug", "uk", "ur", "uz", "vi", "vo", 78 "wo", "xh", "yi", "yo", "za", "zh", "zu" 79 }; 80 81 89 90 94 public void setTidy(BooleanAttribute itidy) { 95 tidy = (itidy.getValue().equals("yes") || itidy.getValue().equals("true")); 96 } 97 98 103 public void setMasterlocaledir(String masterDir) { 104 this.masterDir=masterDir; 105 } 107 108 113 public void setMasterlocalefile(String masterFile) { 114 this.masterFile=masterFile; 115 } 117 118 125 public void execute() throws BuildException { 126 if (verbose) { 128 logLevel = this.getProject().MSG_INFO; 129 } else { 130 logLevel = this.getProject().MSG_DEBUG; 131 } 132 133 log("Searching for XMLC Localization templates in "+srcDir+"...", logLevel); 135 136 boolean wroteFiles = false; 138 boolean touchedTemplate = false; 139 int fileCount = 0; 140 int templateCount = 0; 141 DirectoryScanner ds = this.getDirectoryScanner(srcDir); 142 String [] files = ds.getIncludedFiles(); 143 iterateFiles: for (int i=0; i<files.length; i++) { 144 String file = files[i]; 146 String fileName = file; 147 String fileExt = null; 148 int epos = file.lastIndexOf("."); 149 if (epos>-1) { 150 fileName = file.substring(0,epos); 151 if (epos+1<file.length()) fileExt = file.substring(epos+1); 152 } 153 File templateFile = new File(srcDir, files[i]); 154 long templateLastTouched = templateFile.lastModified(); 155 156 if (fileName.indexOf("_")>0) { 159 String tfile = fileName; 160 if (!tfile.endsWith("_")) tfile += "_"; 161 StringTokenizer st = new StringTokenizer(tfile, "_"); 162 while (st.hasMoreTokens()) { 163 String token = st.nextToken(); 164 int pos = Arrays.binarySearch(countryCodes, token); 165 if (pos>-1 && pos<countryCodes.length && countryCodes[pos].equals(token)) continue iterateFiles; 166 } 167 } 168 169 172 File propFile = null; 176 if (masterFile!=null) { 177 propFile = new File(masterDir, masterFile+".properties"); 178 } else { 179 propFile = new File(srcDir, fileName+".properties"); 180 } 181 183 long propLastTouched = -1; 184 if (!propFile.exists()) propLastTouched = propFile.lastModified(); 185 if (propLastTouched >= templateLastTouched) { 186 if (!touchedTemplate) { 187 templateFile.setLastModified(System.currentTimeMillis()); 189 touchedTemplate = true; 190 } 192 } 193 194 File xmlcFile = new File(srcDir, fileName+".xmlc"); 196 createMasterXMLC: if (propFile.exists() && !xmlcFile.exists()) { 197 BufferedWriter writer = null; 199 try { 200 writer = new BufferedWriter(new FileWriter(xmlcFile)); 202 writer.write("-generate both"); 203 writer.newLine(); 204 writer.flush(); 205 206 if (!touchedTemplate) { 207 templateFile.setLastModified(System.currentTimeMillis()); 209 touchedTemplate = true; 210 } 212 } catch (IOException e) { 213 if (writer!=null) try {writer.close();} catch (IOException ioe) {} 214 } 215 } 216 217 String baseClassFileName = ""; 219 if (packageDir!=null) baseClassFileName = packageDir + "/"; 220 baseClassFileName += fileName + ML + ".class"; 221 File baseClassFile = new File(destDir, baseClassFileName); 222 long baseClassLastTouched = -1; 223 if (!baseClassFile.exists()) { 224 if (!touchedTemplate) { 225 templateFile.setLastModified(System.currentTimeMillis()); 227 touchedTemplate = true; 228 } 230 } else { 231 baseClassLastTouched = baseClassFile.lastModified(); 232 if (forceBuild || 233 templateLastTouched >= baseClassLastTouched || 234 propLastTouched >= baseClassLastTouched) { 235 if (!touchedTemplate) { 236 templateFile.setLastModified(System.currentTimeMillis()); 238 touchedTemplate = true; 239 } 244 } 245 } 246 templateLastTouched = templateFile.lastModified(); 247 249 if (!propFile.exists()) continue; 252 253 DirectoryScanner dsLocales = new DirectoryScanner(); 257 268 int spos = -1; 272 String includeFileName; 273 if (masterFile!=null) { 274 includeFileName = masterFile; 275 dsLocales.setBasedir(masterDir); 276 spos = masterFile.length(); 277 } else { 278 includeFileName = fileName; 279 dsLocales.setBasedir(srcDir); 280 spos = fileName.length(); 281 } 282 String [] includes = {includeFileName+"*.properties"}; 283 dsLocales.setIncludes(includes); 284 dsLocales.scan(); 285 String [] localeFiles = dsLocales.getIncludedFiles(); 286 List locales = new ArrayList(); 287 HashMap propBundleMap = new HashMap(); 288 290 iteratePropFiles: for (int j=0; j<localeFiles.length; j++) { 291 String localeFile = localeFiles[j]; 293 epos = localeFile.length()-11; 294 String localeSubstr = localeFile.substring(spos,epos); 295 if (!(localeSubstr.startsWith("_"))) continue; 296 297 String htmlFile = fileName + localeSubstr + "." + fileExt; 304 File localizedHtmlFile = new File(srcDir, htmlFile); 306 File localizedPropFile = null; 309 if (masterFile!=null) { 310 localizedPropFile = new File(masterDir, localeFile); 311 } else { 312 localizedPropFile = new File(srcDir, localeFile); 313 } 314 316 String xmlcOptionsFileName = fileName + localeSubstr + ".xmlc"; 322 File xmlcOptionsFile = new File(srcDir, xmlcOptionsFileName); 324 boolean autogeneratedOptionsFile = false; 325 createMasterXMLC: if (!xmlcOptionsFile.exists()) { 326 327 XmlcUtils xmlcUtils = XmlcUtils.create(); 333 String clStr = xmlcUtils.buildFullBaseFileName(packageName, packageDir, baseClassFileName); 334 clStr = clStr.replace('\\','.'); 336 clStr = clStr.replace('/','.'); 337 338 BufferedWriter writer = null; 340 try { 341 writer = new BufferedWriter(new FileWriter(xmlcOptionsFile)); 343 writer.write("-implements "+clStr); 344 writer.newLine(); 345 writer.flush(); 346 autogeneratedOptionsFile = true; 347 wroteFiles = true; 348 } catch (IOException e) { 349 if (writer!=null) try {writer.close();} catch (IOException ioe) {} 350 } 351 } 352 353 if (localizedHtmlFile.exists()) { 355 File baseHtmlFile = new File(srcDir, fileName + "." + fileExt); 356 357 long localizedHtmlLastTouched = localizedHtmlFile.lastModified(); 358 long outputPropLastTouched = localizedPropFile.lastModified(); 359 360 boolean rebuild = false; 366 if (forceBuild || 367 touchedTemplate || 368 autogeneratedOptionsFile || 369 propLastTouched >= localizedHtmlLastTouched || 370 outputPropLastTouched >= localizedHtmlLastTouched) { 372 rebuild = true; 373 } 381 382 if (!forceBuild) { 385 String baseXmlcFileName = fileName + ".xmlc"; 386 File baseXmlcFile = new File(srcDir, baseXmlcFileName); 387 if (baseXmlcFile.exists() && baseXmlcFile.canRead()) { 388 long baseXmlcLastTouched = baseXmlcFile.lastModified(); 391 392 if (baseXmlcLastTouched > localizedHtmlLastTouched) { 397 System.out.println(" REBUILD BECAUSE " + baseXmlcFile + " > " + localizedHtmlFile); 398 rebuild = true; 399 } 401 } 402 } 403 404 if (!forceBuild) { 407 String localeXmlcFileName = fileName + localeSubstr + ".xmlc"; 412 File localeXmlcFile = new File(srcDir, localeXmlcFileName); 414 if (localeXmlcFile.exists() && localeXmlcFile.canRead()) { 415 long localeXmlcLastTouched = localeXmlcFile.lastModified(); 418 419 if (localeXmlcLastTouched > localizedHtmlLastTouched) { 424 rebuild = true; 425 } 427 } 428 } 429 430 if (!rebuild) { 431 log(" Template up-to-date: "+localizedHtmlFile.getName(), logLevel); 432 continue iteratePropFiles; 433 } 434 } 435 436 StringTokenizer st = new StringTokenizer(localeSubstr, "_"); 438 String language = ""; 439 String country = ""; 440 String variant = null; 441 if (st.hasMoreTokens()) language = st.nextToken(); 442 if (st.hasMoreTokens()) country = st.nextToken(); 443 if (st.hasMoreTokens()) { 444 String sep = ""; 445 while (st.hasMoreTokens()) { 446 if (variant==null) variant = st.nextToken(); 447 else variant += st.nextToken(); 448 sep = "_"; 449 } 450 } 451 452 Locale targetLocale = null; 454 if (variant!=null) targetLocale = new Locale(language, country, variant); 455 else targetLocale = new Locale(language, country); 456 locales.add(targetLocale); 457 458 File localePropFile = null; 463 if (masterFile!=null) { 464 localePropFile = new File(masterDir, masterFile+localeSubstr+".properties"); 465 } else { 466 localePropFile = new File(srcDir, fileName+localeSubstr+".properties"); 467 } 468 if (!localePropFile.exists()) { 470 log(" Unable to read localization properties file "+localePropFile, this.getProject().MSG_WARN); 471 continue; 472 } 473 PropertyResourceBundle rb = null; 474 try {rb = new PropertyResourceBundle(new FileInputStream(localePropFile));} 475 catch (Exception e) { 476 log(" Unable to create resource bundle for file "+localePropFile, this.getProject().MSG_WARN); 477 continue; 478 } 479 propBundleMap.put(localeSubstr, rb); 480 } 482 if (locales.size()==0) continue; 484 485 log("...Generating localized templates"); 487 StringBuffer sb = new StringBuffer (5000); 488 try { 489 FileReader fr = new FileReader(templateFile); 490 BufferedReader br = new BufferedReader(fr); 491 while (true) { 492 String str = br.readLine(); 493 if (str==null) break; 494 sb.append(str); 495 sb.append(sep); 496 } 497 br.close(); 498 } catch (IOException e) { 499 System.err.println ("Error reading template: "+e); 500 continue; 501 } 502 String masterTemplateStr = sb.toString(); 503 log(" Loaded template "+file, logLevel); 504 fileCount++; 505 506 List masterKeyList = new ArrayList(100); 512 List masterValList = new ArrayList(100); 513 try { 514 FileReader fr = new FileReader(propFile); 515 BufferedReader br = new BufferedReader(fr); 516 while (true) { 517 String str = br.readLine(); 519 if (str==null) break; 520 str = str.trim(); 521 522 if (str.startsWith("#")) continue; 524 525 int eqpos = str.indexOf('='); 527 if (eqpos<0) continue; 528 529 String key = (""+str.substring(0,eqpos)).trim(); 531 String val = (""+str.substring(eqpos+1)).trim(); 532 masterKeyList.add(key); 533 masterValList.add(val); 534 } 535 br.close(); 536 } catch (IOException e) { 537 System.err.println ("Error reading template: "+e); 538 continue; 539 } 540 541 Object locArray[] = locales.toArray(); 543 iterateTemplates: for (int j=0; j<locArray.length; j++) { 544 List locList = new ArrayList(); 546 Locale loc = (Locale) locArray[j]; 547 String locExt = ""; 548 String buf = loc.getLanguage(); 549 if (buf!=null && buf.length()>0) { 550 locExt+="_"+buf; 551 locList.add(0,propBundleMap.get(locExt)); 552 buf = loc.getCountry(); 553 if (buf!=null && buf.length()>0) { 554 locExt+="_"+buf; 555 locList.add(0,propBundleMap.get(locExt)); 556 buf = loc.getVariant(); 557 if (buf!=null && buf.length()>0) { 558 locExt+="_"+buf; 559 locList.add(0,propBundleMap.get(locExt)); 560 } 561 } 562 } 563 564 String templateStr = new String (masterTemplateStr); 567 568 Map lmap = new HashMap(100); 570 for (int k=0, max=masterKeyList.size(); k<max; k++) { 571 String key = (String ) masterKeyList.get(k); 573 String val = (String ) masterValList.get(k); 574 575 String lczval = null; 577 Iterator it = locList.iterator(); 578 iterate_rbs: while (it.hasNext()) { 579 ResourceBundle rb = (ResourceBundle) it.next(); 580 if (rb==null) continue; 582 try {lczval = rb.getString(key);} 583 catch (MissingResourceException e) {} 584 if (lczval!=null) break iterate_rbs; 585 } 586 if (lczval==null) continue; 587 588 String hash = "@"+Integer.toHexString(lczval.hashCode()); 593 templateStr = qualifiedStrReplace(templateStr, val, hash); 594 lmap.put(hash, lczval); 595 } 596 597 Iterator it = lmap.keySet().iterator(); 601 while (it.hasNext()) { 602 String hashkey = (String ) it.next(); 603 String lczval = (String ) lmap.get(hashkey); 604 templateStr = strReplace(templateStr, hashkey, lczval); 605 } 606 607 try { 609 File outputFile = new File(srcDir, fileName+locExt+"."+fileExt); 610 FileWriter fw = new FileWriter(outputFile); 611 BufferedWriter bw = new BufferedWriter(fw); 612 bw.write(templateStr); 613 bw.close(); 614 wroteFiles = true; 615 templateCount++; 616 } catch (IOException e) { 617 System.err.println ("Error writing localized template: "+e); 618 continue; 619 } 620 } } 623 if (touchedTemplate || wroteFiles) { 624 log("...Invoking XMLC precompiler taskdef"); 627 int origLogLevel = logLevel; 628 logLevel = this.getProject().MSG_DEBUG; 629 super.execute(); 630 logLevel = origLogLevel; 631 } 632 633 647 649 log("Finished!", logLevel); 651 if (fileCount!=0 || templateCount!=0 || verbose) log("Processed "+files.length+" source files, found "+fileCount+" master templates, created "+templateCount+" new localized templates"+(fileCount>=0 && templateCount==0 ? " (all files up-to-date)" : "")); 652 } 653 654 659 protected String qualifiedStrReplace(String str, String str1, String str2) { 660 int spos = 0; 661 while (true) { 662 int found = str.indexOf(str1, spos); 664 if (found<0) break; 665 666 if (str2!=null && isQualified(str, found)) { 668 str = str.substring(0,found)+str2+str.substring(found+str1.length()); 669 spos = found + str2.length(); 670 } else { 671 spos = found + str1.length(); 672 } 673 } 674 return str; 675 } 676 677 680 protected String strReplace(String str, String str1, String str2) { 681 StringBuffer ret = new StringBuffer (); 682 int start = 0; 683 int found = str.indexOf(str1); 684 while (found >= 0) { 685 if (found > start) { 687 ret.append(str.substring(start, found)); 688 } 689 690 if (str2!=null) { 692 ret.append(str2); 693 } 694 695 start = found + str1.length(); 697 found = str.indexOf(str1,start); 698 } 699 700 if (str.length() > start) { 702 ret.append(str.substring(start, str.length())); 703 } 704 705 return ret.toString(); 706 } 707 708 protected boolean isQualified(String str, int fpos) { 709 if (embeddedInToken(str, fpos, "id=\"","\"")) return false; 710 if (embeddedInToken(str, fpos, "class=\"","\"")) return false; 711 return true; 712 } 713 714 protected boolean embeddedInToken(String str, int fpos, String stoken, String etoken) { 715 int spos = str.lastIndexOf(stoken, fpos); 718 if (spos<0) return false; 719 720 int epos = str.indexOf(etoken, spos+stoken.length()); 724 if (epos<0 || epos<fpos) return false; 725 else return true; 726 } 727 728 732 class InternalJavac extends Javac { 733 734 public InternalJavac() { 735 this.setTaskName(Localize.this.getTaskName()); 737 } 738 739 public void setProject(Project iproject) { 740 this.setProject(iproject); 741 } 742 } 743 744 public static void main(String args[]) { 745 Localize loc = new Localize(); 746 747 System.out.println(loc.qualifiedStrReplace("<select id=\"AbstractBComponent_DebugLevel\" name=\"D1\" size=\"1\">", "Debug", "zipper")); 749 750 System.out.println(loc.qualifiedStrReplace("<select id=\"Abstract\" blah=\"DebugLevel\" name=\"D1\" size=\"1\">", "Debug", "zipper")); 752 } 753 } 754 755 | Popular Tags |