1 52 53 package freemarker.template; 54 55 import java.io.*; 56 import java.util.*; 57 58 import freemarker.cache.*; 59 import freemarker.core.*; 60 import freemarker.template.utility.*; 61 62 80 81 public class Configuration extends Configurable implements Cloneable { 82 public static final String DEFAULT_ENCODING_KEY = "default_encoding"; 83 public static final String LOCALIZED_LOOKUP_KEY = "localized_lookup"; 84 public static final String STRICT_SYNTAX_KEY = "strict_syntax"; 85 public static final String WHITESPACE_STRIPPING_KEY = "whitespace_stripping"; 86 public static final String CACHE_STORAGE_KEY = "cache_storage"; 87 public static final String TEMPLATE_UPDATE_DELAY_KEY = "template_update_delay"; 88 public static final String AUTO_IMPORT_KEY = "auto_import"; 89 public static final String AUTO_INCLUDE_KEY = "auto_include"; 90 91 private static Configuration defaultConfig = new Configuration(); 92 private static String cachedVersion; 93 private boolean strictSyntax = true, localizedLookup = true, whitespaceStripping = true; 94 private TemplateCache cache; 95 private HashMap variables = new HashMap(); 96 private HashMap encodingMap = new HashMap(); 97 private Map autoImportMap = new HashMap(); 98 private ArrayList autoImports = new ArrayList(), autoIncludes = new ArrayList(); 99 private String defaultEncoding = SecurityUtilities.getSystemProperty("file.encoding"); 100 101 102 public Configuration() { 103 cache = new TemplateCache(); 104 cache.setConfiguration(this); 105 cache.setDelay(5000); 106 loadBuiltInSharedVariables(); 107 } 108 109 public Object clone() { 110 try { 111 Configuration copy = (Configuration)super.clone(); 112 copy.variables = new HashMap(variables); 113 copy.encodingMap = new HashMap(encodingMap); 114 copy.createTemplateCache(cache.getTemplateLoader(), cache.getCacheStorage()); 115 return copy; 116 } catch (CloneNotSupportedException e) { 117 throw new RuntimeException ("Clone is not supported, but it should be: " + e.getMessage()); 118 } 119 } 120 121 private void loadBuiltInSharedVariables() { 122 variables.put("capture_output", new CaptureOutput()); 123 variables.put("compress", StandardCompress.INSTANCE); 124 variables.put("html_escape", new HtmlEscape()); 125 variables.put("normalize_newlines", new NormalizeNewlines()); 126 variables.put("xml_escape", new XmlEscape()); 127 } 128 129 178 public void loadBuiltInEncodingMap() { 179 encodingMap.clear(); 180 encodingMap.put("ar", "ISO-8859-6"); 181 encodingMap.put("be", "ISO-8859-5"); 182 encodingMap.put("bg", "ISO-8859-5"); 183 encodingMap.put("ca", "ISO-8859-1"); 184 encodingMap.put("cs", "ISO-8859-2"); 185 encodingMap.put("da", "ISO-8859-1"); 186 encodingMap.put("de", "ISO-8859-1"); 187 encodingMap.put("el", "ISO-8859-7"); 188 encodingMap.put("en", "ISO-8859-1"); 189 encodingMap.put("es", "ISO-8859-1"); 190 encodingMap.put("et", "ISO-8859-1"); 191 encodingMap.put("fi", "ISO-8859-1"); 192 encodingMap.put("fr", "ISO-8859-1"); 193 encodingMap.put("hr", "ISO-8859-2"); 194 encodingMap.put("hu", "ISO-8859-2"); 195 encodingMap.put("is", "ISO-8859-1"); 196 encodingMap.put("it", "ISO-8859-1"); 197 encodingMap.put("iw", "ISO-8859-8"); 198 encodingMap.put("ja", "Shift_JIS"); 199 encodingMap.put("ko", "EUC-KR"); 200 encodingMap.put("lt", "ISO-8859-2"); 201 encodingMap.put("lv", "ISO-8859-2"); 202 encodingMap.put("mk", "ISO-8859-5"); 203 encodingMap.put("nl", "ISO-8859-1"); 204 encodingMap.put("no", "ISO-8859-1"); 205 encodingMap.put("pl", "ISO-8859-2"); 206 encodingMap.put("pt", "ISO-8859-1"); 207 encodingMap.put("ro", "ISO-8859-2"); 208 encodingMap.put("ru", "ISO-8859-5"); 209 encodingMap.put("sh", "ISO-8859-5"); 210 encodingMap.put("sk", "ISO-8859-2"); 211 encodingMap.put("sl", "ISO-8859-2"); 212 encodingMap.put("sq", "ISO-8859-2"); 213 encodingMap.put("sr", "ISO-8859-5"); 214 encodingMap.put("sv", "ISO-8859-1"); 215 encodingMap.put("tr", "ISO-8859-9"); 216 encodingMap.put("uk", "ISO-8859-5"); 217 encodingMap.put("zh", "GB2312"); 218 encodingMap.put("zh_TW", "Big5"); 219 } 220 221 226 public void clearEncodingMap() { 227 encodingMap.clear(); 228 } 229 230 245 static public Configuration getDefaultConfiguration() { 246 return defaultConfig; 247 } 248 249 257 static public void setDefaultConfiguration(Configuration config) { 258 defaultConfig = config; 259 } 260 261 272 public synchronized void setTemplateLoader(TemplateLoader loader) { 273 createTemplateCache(loader, cache.getCacheStorage()); 274 } 275 276 private void createTemplateCache(TemplateLoader loader, CacheStorage storage) 277 { 278 TemplateCache oldCache = cache; 279 cache = new TemplateCache(loader, storage); 280 cache.setDelay(oldCache.getDelay()); 281 cache.setConfiguration(this); 282 cache.setLocalizedLookup(localizedLookup); 283 } 284 288 public TemplateLoader getTemplateLoader() 289 { 290 return cache.getTemplateLoader(); 291 } 292 293 public synchronized void setCacheStorage(CacheStorage storage) { 294 createTemplateCache(cache.getTemplateLoader(), storage); 295 } 296 297 300 public void setDirectoryForTemplateLoading(File dir) throws IOException { 301 TemplateLoader tl = getTemplateLoader(); 302 if (tl instanceof FileTemplateLoader) { 303 String path = ((FileTemplateLoader) tl).baseDir.getCanonicalPath(); 304 if (path.equals(dir.getCanonicalPath())) 305 return; 306 } 307 setTemplateLoader(new FileTemplateLoader(dir)); 308 } 309 310 322 public void setServletContextForTemplateLoading(Object sctxt, String path) { 323 try { 324 if (path == null) { 325 setTemplateLoader( (TemplateLoader) 326 ClassUtil.forName("freemarker.cache.WebappTemplateLoader") 327 .getConstructor(new Class []{ClassUtil.forName("javax.servlet.ServletContext")}) 328 .newInstance(new Object []{sctxt}) ); 329 } 330 else { 331 setTemplateLoader( (TemplateLoader) 332 ClassUtil.forName("freemarker.cache.WebappTemplateLoader") 333 .getConstructor(new Class []{ClassUtil.forName("javax.servlet.ServletContext"), String .class}) 334 .newInstance(new Object []{sctxt, path}) ); 335 } 336 } catch (Exception exc) { 337 throw new RuntimeException ("Internal FreeMarker error: " + exc); 338 } 339 } 340 341 345 public void setClassForTemplateLoading(Class clazz, String pathPrefix) { 346 setTemplateLoader(new ClassTemplateLoader(clazz, pathPrefix)); 347 } 348 349 354 public void setTemplateUpdateDelay(int delay) { 355 cache.setDelay(1000L * delay); 356 } 357 358 366 367 public void setStrictSyntaxMode(boolean b) { 368 strictSyntax = b; 369 } 370 371 377 public boolean getStrictSyntaxMode() { 378 return strictSyntax; 379 } 380 381 385 public void setWhitespaceStripping(boolean b) { 386 whitespaceStripping = b; 387 } 388 389 395 public boolean getWhitespaceStripping() { 396 return whitespaceStripping; 397 } 398 399 402 public Template getTemplate(String name) throws IOException { 403 Locale loc = getLocale(); 404 return getTemplate(name, loc, getEncoding(loc), true); 405 } 406 407 410 public Template getTemplate(String name, Locale locale) throws IOException { 411 return getTemplate(name, locale, getEncoding(locale), true); 412 } 413 414 417 public Template getTemplate(String name, String encoding) throws IOException { 418 return getTemplate(name, getLocale(), encoding, true); 419 } 420 421 424 public Template getTemplate(String name, Locale locale, String encoding) throws IOException { 425 return getTemplate(name, locale, encoding, true); 426 } 427 428 438 public Template getTemplate(String name, Locale locale, String encoding, boolean parse) throws IOException { 439 Template result = cache.getTemplate(name, locale, encoding, parse); 440 if (result == null) { 441 throw new FileNotFoundException("Template " + name + " not found."); 442 } 443 return result; 444 } 445 446 451 public void setDefaultEncoding(String encoding) { 452 defaultEncoding = encoding; 453 } 454 455 460 public String getDefaultEncoding() { 461 return defaultEncoding; 462 } 463 464 472 public String getEncoding(Locale loc) { 473 String charset = (String ) encodingMap.get(loc.toString()); 475 if (charset == null) { 476 if (loc.getVariant().length() > 0) { 477 Locale l = new Locale(loc.getLanguage(), loc.getCountry()); 478 charset = (String ) encodingMap.get(l.toString()); 479 if (charset != null) { 480 encodingMap.put(loc.toString(), charset); 481 } 482 } 483 charset = (String ) encodingMap.get(loc.getLanguage()); 484 if (charset != null) { 485 encodingMap.put(loc.toString(), charset); 486 } 487 } 488 return charset != null ? charset : defaultEncoding; 489 } 490 491 500 public void setEncoding(Locale locale, String encoding) { 501 encodingMap.put(locale.toString(), encoding); 502 } 503 504 520 public void setSharedVariable(String name, TemplateModel tm) { 521 variables.put(name, tm); 522 } 523 524 530 public Set getSharedVariableNames() { 531 return new HashSet(variables.keySet()); 532 } 533 534 541 public void setSharedVariable(String name, Object obj) throws TemplateModelException { 542 setSharedVariable(name, getObjectWrapper().wrap(obj)); 543 } 544 545 559 public void setAllSharedVariables(TemplateHashModelEx hash) throws TemplateModelException { 560 TemplateModelIterator keys = hash.keys().iterator(); 561 TemplateModelIterator values = hash.values().iterator(); 562 while(keys.hasNext()) 563 { 564 setSharedVariable(((TemplateScalarModel)keys.next()).getAsString(), values.next()); 565 } 566 } 567 568 580 public TemplateModel getSharedVariable(String name) { 581 return (TemplateModel) variables.get(name); 582 } 583 584 587 public void clearSharedVariables() { 588 variables.clear(); 589 loadBuiltInSharedVariables(); 590 } 591 592 597 public void clearTemplateCache() { 598 cache.clear(); 599 } 600 601 605 public boolean getLocalizedLookup() { 606 return cache.getLocalizedLookup(); 607 } 608 609 613 public void setLocalizedLookup(boolean localizedLookup) { 614 this.localizedLookup = localizedLookup; 615 cache.setLocalizedLookup(localizedLookup); 616 } 617 618 671 public void setSetting(String key, String value) throws TemplateException { 672 if ("TemplateUpdateInterval".equalsIgnoreCase(key)) { 673 key = TEMPLATE_UPDATE_DELAY_KEY; 674 } else if ("DefaultEncoding".equalsIgnoreCase(key)) { 675 key = DEFAULT_ENCODING_KEY; 676 } 677 try { 678 if (DEFAULT_ENCODING_KEY.equals(key)) { 679 setDefaultEncoding(value); 680 } else if (LOCALIZED_LOOKUP_KEY.equals(key)) { 681 setLocalizedLookup(StringUtil.getYesNo(value)); 682 } else if (STRICT_SYNTAX_KEY.equals(key)) { 683 setStrictSyntaxMode(StringUtil.getYesNo(value)); 684 } else if (WHITESPACE_STRIPPING_KEY.equals(key)) { 685 setWhitespaceStripping(StringUtil.getYesNo(value)); 686 } else if (CACHE_STORAGE_KEY.equals(key)) { 687 if (value.indexOf('.') == -1) { 688 int strongSize = 0; 689 int softSize = 0; 690 Map map = StringUtil.parseNameValuePairList( 691 value, String.valueOf(Integer.MAX_VALUE)); 692 Iterator it = map.entrySet().iterator(); 693 while (it.hasNext()) { 694 Map.Entry ent = (Map.Entry) it.next(); 695 String pname = (String ) ent.getKey(); 696 int pvalue; 697 try { 698 pvalue = Integer.parseInt((String ) ent.getValue()); 699 } catch (NumberFormatException e) { 700 throw invalidSettingValueException(key, value); 701 } 702 if ("soft".equalsIgnoreCase(pname)) { 703 softSize = pvalue; 704 } else if ("strong".equalsIgnoreCase(pname)) { 705 strongSize = pvalue; 706 } else { 707 throw invalidSettingValueException(key, value); 708 } 709 } 710 if (softSize == 0 && strongSize == 0) { 711 throw invalidSettingValueException(key, value); 712 } 713 setCacheStorage(new MruCacheStorage(strongSize, softSize)); 714 } else { 715 setCacheStorage((CacheStorage) ClassUtil.forName(value) 716 .newInstance()); 717 } 718 } else if (TEMPLATE_UPDATE_DELAY_KEY.equals(key)) { 719 setTemplateUpdateDelay(Integer.parseInt(value)); 720 } else if (AUTO_INCLUDE_KEY.equals(key)) { 721 setAutoIncludes(new SettingStringParser(value).parseAsList()); 722 } else if (AUTO_IMPORT_KEY.equals(key)) { 723 setAutoImports(new SettingStringParser(value).parseAsImportList()); 724 } else { 725 super.setSetting(key, value); 726 } 727 } catch(TemplateException e) { 728 throw e; 729 } catch(Exception e) { 730 throw new TemplateException( 731 "Failed to set setting " + key + " to value " + value, 732 e, getEnvironment()); 733 } 734 } 735 736 737 744 public synchronized void addAutoImport(String namespace, String template) { 745 autoImports.remove(namespace); 746 autoImports.add(namespace); 747 autoImportMap.put(namespace, template); 748 } 749 750 754 755 public synchronized void removeAutoImport(String namespace) { 756 autoImports.remove(namespace); 757 autoImportMap.remove(namespace); 758 } 759 760 764 765 public synchronized void setAutoImports(Map map) { 766 autoImports = new ArrayList(map.keySet()); 767 if (map instanceof HashMap) { 768 autoImportMap = (Map) ((HashMap) map).clone(); 769 } 770 else if (map instanceof SortedMap) { 771 autoImportMap = new TreeMap(map); 772 } 773 else { 774 autoImportMap = new HashMap(map); 775 } 776 } 777 778 void doAutoImports(Environment env) throws TemplateException, IOException { 779 for (int i=0; i<autoImports.size(); i++) { 780 String namespace = (String ) autoImports.get(i); 781 String templateName = (String ) autoImportMap.get(namespace); 782 env.importLib(templateName, namespace); 783 } 784 } 785 786 791 792 public synchronized void addAutoInclude(String templateName) { 793 autoIncludes.remove(templateName); 794 autoIncludes.add(templateName); 795 } 796 797 801 public synchronized void setAutoIncludes(List templateNames) { 802 autoIncludes.clear(); 803 Iterator it = templateNames.iterator(); 804 while (it.hasNext()) { 805 Object o = it.next(); 806 if (!(o instanceof String )) { 807 throw new IllegalArgumentException ("List items must be String-s."); 808 } 809 autoIncludes.add(o); 810 } 811 } 812 813 817 818 public synchronized void removeAutoInclude(String templateName) { 819 autoIncludes.remove(templateName); 820 } 821 822 854 public static String getVersionNumber() { 855 if (cachedVersion != null) { 856 return cachedVersion; 857 } 858 try { 859 Properties vp = new Properties(); 860 InputStream ins = Configuration.class.getClassLoader() 861 .getResourceAsStream("freemarker/version.properties"); 862 if (ins == null) { 863 throw new RuntimeException ("Version file is missing."); 864 } else { 865 try { 866 vp.load(ins); 867 } finally { 868 ins.close(); 869 } 870 String v = vp.getProperty("version"); 871 if (v == null) { 872 throw new RuntimeException ("Version file is corrupt: version key is missing."); 873 } 874 cachedVersion = v; 875 } 876 return cachedVersion; 877 } catch (IOException e) { 878 throw new RuntimeException ("Failed to load version file: " + e); 879 } 880 } 881 882 void doAutoIncludes(Environment env) throws TemplateException, IOException { 883 for (int i = 0; i < autoIncludes.size(); i++) { 884 String templateName = (String ) autoIncludes.get(i); 885 Template template = getTemplate(templateName, env.getLocale()); 886 env.include(template); 887 } 888 } 889 890 } 891 | Popular Tags |