1 /* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.clearsilver.jsilver; 18 19 import com.google.clearsilver.jsilver.autoescape.EscapeMode; 20 import com.google.clearsilver.jsilver.data.NoOpStringInternStrategy; 21 import com.google.clearsilver.jsilver.data.StringInternStrategy; 22 23 import java.util.Map; 24 25 /** 26 * Options for JSilver. 27 * 28 * Note: Setter methods also return reference to this, allowing options to be defined in one 29 * statement. 30 * 31 * e.g. new JSilver(..., new JSilverOptions().setSomething(true).setAnother(false)); 32 * 33 * @see JSilver 34 */ 35 public class JSilverOptions implements Cloneable { 36 37 private boolean cacheTemplates = true; 38 private boolean compileTemplates = false; 39 private int initialBufferSize = 8192; 40 private boolean ignoreAttributes = false; 41 private Map<Object, String> precompiledTemplateMap = null; 42 private boolean useStrongCacheReferences = false; 43 private EscapeMode escapeMode = EscapeMode.ESCAPE_NONE; 44 private boolean propagateEscapeStatus = false; 45 46 /** 47 * A pool of strings used to optimize HDF parsing. 48 * 49 * String interning has been shown to improve GC performance, but also to increase CPU usage. To 50 * avoid any possible unexpected changes in behavior it is disabled by default. 51 */ 52 private StringInternStrategy stringInternStrategy = new NoOpStringInternStrategy(); 53 54 /** 55 * This flag is used to enable logging of all variables whose values are modified by auto escaping 56 * or <cs escape> commands. These will be logged at {@code Level.WARNING}. 57 */ 58 private boolean logEscapedVariables = false; 59 private boolean useOutputBufferPool = false; 60 private boolean stripHtmlWhiteSpace = false; 61 private boolean stripStructuralWhiteSpace = false; 62 private boolean allowGlobalDataModification = false; 63 private boolean keepTemplateCacheFresh = false; 64 private int loadPathCacheSize = 1000; 65 66 // When adding fields, ensure you: 67 // * add getter. 68 // * add setter (which returns this). 69 // * add to clone() method if necessary. 70 71 /** 72 * Set the initial size of the load path cache container. Setting this to 0 causes load path cache 73 * to be disabled. 74 */ 75 public JSilverOptions setLoadPathCacheSize(int loadPathCacheSize) { 76 this.loadPathCacheSize = loadPathCacheSize; 77 return this; 78 } 79 80 /** 81 * @see #setLoadPathCacheSize(int) 82 */ 83 public int getLoadPathCacheSize() { 84 return loadPathCacheSize; 85 } 86 87 /** 88 * Whether to cache templates. This will only ever load and parse a template from disk once. Best 89 * switched on for production but left off for production (so you can update templates without 90 * restarting). 91 */ 92 public JSilverOptions setCacheTemplates(boolean cacheTemplates) { 93 this.cacheTemplates = cacheTemplates; 94 return this; 95 } 96 97 /** 98 * @see #setCacheTemplates(boolean) 99 */ 100 public boolean getCacheTemplates() { 101 return cacheTemplates; 102 } 103 104 /** 105 * Compile templates to Java byte code. This slows down the initial render as it performs a 106 * compilation step, but then subsequent render are faster. 107 * 108 * Compiled templates are always cached. 109 * 110 * WARNING: This functionality is experimental. Use with caution. 111 */ 112 public JSilverOptions setCompileTemplates(boolean compileTemplates) { 113 this.compileTemplates = compileTemplates; 114 return this; 115 } 116 117 /** 118 * @see #setCompileTemplates(boolean) 119 */ 120 public boolean getCompileTemplates() { 121 return compileTemplates; 122 } 123 124 /** 125 * If set, then HDF attributes in HDF files will be ignored and not stored in the Data object 126 * filled by the parser. Default is {@code false}. Many applications use HDF attributes only in 127 * template preprocessing (like translation support) and never in production servers where the 128 * templates are rendered. By disabling attribute parsing, these applications can save on memory 129 * for storing HDF structures read from files. 130 */ 131 public JSilverOptions setIgnoreAttributes(boolean ignoreAttributes) { 132 this.ignoreAttributes = ignoreAttributes; 133 return this; 134 } 135 136 /** 137 * @see #setIgnoreAttributes(boolean) 138 */ 139 public boolean getIgnoreAttributes() { 140 return ignoreAttributes; 141 } 142 143 /** 144 * Initial buffer size used when rendering directly to a string. 145 */ 146 public JSilverOptions setInitialBufferSize(int initialBufferSize) { 147 this.initialBufferSize = initialBufferSize; 148 return this; 149 } 150 151 /** 152 * @see #setInitialBufferSize(int) 153 */ 154 public int getInitialBufferSize() { 155 return initialBufferSize; 156 } 157 158 /** 159 * Optional mapping of TemplateLoader keys to Template instances that will be queried when loading 160 * a template. If the Template is found it is returned. If not, the next template loader is 161 * consulted. 162 * 163 * @param precompiledTemplateMap map of TemplateLoader keys to corresponding class names that 164 * should be valid BaseCompiledTemplate subclasses. Set to {@code null} (default) to not 165 * load precompiled templates. 166 */ 167 public JSilverOptions setPrecompiledTemplateMap(Map<Object, String> precompiledTemplateMap) { 168 this.precompiledTemplateMap = precompiledTemplateMap; 169 return this; 170 } 171 172 /** 173 * @see #setPrecompiledTemplateMap(java.util.Map) 174 * @return a mapping of TemplateLoader keys to corresponding BaseCompiledTemplate class names, or 175 * {@code null} (default) if no precompiled templates should be preloaded. 176 */ 177 public Map<Object, String> getPrecompiledTemplateMap() { 178 return precompiledTemplateMap; 179 } 180 181 /** 182 * If {@code true}, then the template cache will use strong persistent references for the values. 183 * If {@code false} (default) it will use soft references. Warning: The cache size is unbounded so 184 * only use this option if you have sufficient memory to load all the Templates into memory. 185 */ 186 public JSilverOptions setUseStrongCacheReferences(boolean value) { 187 this.useStrongCacheReferences = value; 188 return this; 189 } 190 191 /** 192 * @see #setUseStrongCacheReferences(boolean) 193 */ 194 public boolean getUseStrongCacheReferences() { 195 return useStrongCacheReferences; 196 } 197 198 /** 199 * @see #setEscapeMode(com.google.clearsilver.jsilver.autoescape.EscapeMode) 200 */ 201 public EscapeMode getEscapeMode() { 202 return escapeMode; 203 } 204 205 /** 206 * Escape any template being rendered with the given escaping mode. If the mode is ESCAPE_HTML, 207 * ESCAPE_URL or ESCAPE_JS, the corresponding escaping will be all variables in the template. If 208 * the mode is ESCAPE_AUTO, enable <a href="http://go/autoescapecs">auto escaping</a> on 209 * templates. For each variable in the template, this will determine what type of escaping should 210 * be applied to the variable, and automatically apply this escaping. This flag can be overriden 211 * by setting appropriate HDF variables before loading a template. If Config.AutoEscape is 1, auto 212 * escaping is enabled. If Config.VarEscapeMode is set to one of 'html', 'js' or 'url', the 213 * corresponding escaping is applied to all variables. 214 * 215 * @param escapeMode 216 */ 217 public JSilverOptions setEscapeMode(EscapeMode escapeMode) { 218 this.escapeMode = escapeMode; 219 return this; 220 } 221 222 /** 223 * @see #setPropagateEscapeStatus 224 */ 225 public boolean getPropagateEscapeStatus() { 226 return propagateEscapeStatus; 227 } 228 229 /** 230 * Only used for templates that are being <a href="http://go/autoescapecs">auto escaped</a>. If 231 * {@code true} and auto escaping is enabled, variables created by <cs set> or <cs 232 * call> commands are not auto escaped if they are assigned constant or escaped values. This is 233 * disabled by default. 234 * 235 * @see #setEscapeMode 236 */ 237 public JSilverOptions setPropagateEscapeStatus(boolean propagateEscapeStatus) { 238 this.propagateEscapeStatus = propagateEscapeStatus; 239 return this; 240 } 241 242 /** 243 * Sets the {@link StringInternStrategy} object that will be used to optimize HDF parsing. 244 * 245 * <p> 246 * Set value should not be {@code null} as it can cause {@link NullPointerException}. 247 * 248 * @param stringInternStrategy - {@link StringInternStrategy} object 249 */ 250 public void setStringInternStrategy(StringInternStrategy stringInternStrategy) { 251 if (stringInternStrategy == null) { 252 throw new IllegalArgumentException("StringInternStrategy should not be null."); 253 } 254 this.stringInternStrategy = stringInternStrategy; 255 } 256 257 /** 258 * Returns {@link StringInternStrategy} object that is used for optimization of HDF parsing. 259 * 260 * <p> 261 * The returned value should never be {@code null}. 262 * 263 * @return currently used {@link StringInternStrategy} object. 264 */ 265 public StringInternStrategy getStringInternStrategy() { 266 return stringInternStrategy; 267 } 268 269 /** 270 * If {@code true}, then use a threadlocal buffer pool for holding rendered output when outputting 271 * to String. Assumes that render() is called from a thread and that thread will not reenter 272 * render() while it is running. If {@code false}, a new buffer is allocated for each request 273 * where an Appendable output object was not provided. 274 */ 275 public JSilverOptions setUseOutputBufferPool(boolean value) { 276 this.useOutputBufferPool = value; 277 return this; 278 } 279 280 /** 281 * @see #setUseOutputBufferPool(boolean) 282 */ 283 public boolean getUseOutputBufferPool() { 284 return useOutputBufferPool; 285 } 286 287 /** 288 * If {@code true}, then unnecessary whitespace will be stripped from the output. 'Unnecessary' is 289 * meant in terms of HTML output. See 290 * {@link com.google.clearsilver.jsilver.template.HtmlWhiteSpaceStripper} for more info. 291 */ 292 public JSilverOptions setStripHtmlWhiteSpace(boolean value) { 293 this.stripHtmlWhiteSpace = value; 294 return this; 295 } 296 297 /** 298 * @see #setStripHtmlWhiteSpace(boolean) 299 */ 300 public boolean getStripHtmlWhiteSpace() { 301 return stripHtmlWhiteSpace; 302 } 303 304 /** 305 * If {@code true}, then structural whitespace will be stripped from the output. This allows 306 * templates to be written to more closely match normal programming languages. See 307 * {@link com.google.clearsilver.jsilver.syntax.StructuralWhitespaceStripper} for more info. 308 */ 309 public JSilverOptions setStripStructuralWhiteSpace(boolean value) { 310 this.stripStructuralWhiteSpace = value; 311 return this; 312 } 313 314 /** 315 * @see #setStripHtmlWhiteSpace(boolean) 316 */ 317 public boolean getStripStructuralWhiteSpace() { 318 return stripStructuralWhiteSpace; 319 } 320 321 /** 322 * Use this method to disable wrapping the global HDF with an UnmodifiableData object which 323 * prevents modification. This flag is here in case there are corner cases or performance reasons 324 * that someone may want to disable this protection. 325 * 326 * Should not be set to {@code true} unless incompatibilities or performance issues found. Note, 327 * that setting to {@code true} could introduce bugs in templates that acquire local references to 328 * the global data structure and then try to modify them, which is not the intended behavior. 329 * Allowing global data modification during rendering is not compatible with the recently fixed 330 * JNI Clearsilver library. 331 * 332 * TODO: Remove once legacy mode is no longer needed. 333 * 334 * @param allowGlobalDataModification {@code true} if you want to avoid wrapping the global HDF so 335 * that all writes to it during rendering are prevented and throw an exception. 336 * @return this object. 337 */ 338 public JSilverOptions setAllowGlobalDataModification(boolean allowGlobalDataModification) { 339 this.allowGlobalDataModification = allowGlobalDataModification; 340 return this; 341 } 342 343 /** 344 * @see #setAllowGlobalDataModification(boolean) 345 */ 346 public boolean getAllowGlobalDataModification() { 347 return allowGlobalDataModification; 348 } 349 350 /** 351 * @param keepTemplateCacheFresh {@code true} to have the template cache call 352 * {@link com.google.clearsilver.jsilver.resourceloader.ResourceLoader#getResourceVersionId(String)} 353 * to check if it should refresh its cache entries (this incurs a small performance penalty 354 * each time the cache is accessed) 355 * @return this object 356 */ 357 public JSilverOptions setKeepTemplateCacheFresh(boolean keepTemplateCacheFresh) { 358 this.keepTemplateCacheFresh = keepTemplateCacheFresh; 359 return this; 360 } 361 362 /** 363 * @see #setKeepTemplateCacheFresh(boolean) 364 */ 365 public boolean getKeepTemplateCacheFresh() { 366 return keepTemplateCacheFresh; 367 } 368 369 @Override 370 public JSilverOptions clone() { 371 try { 372 return (JSilverOptions) super.clone(); 373 } catch (CloneNotSupportedException impossible) { 374 throw new AssertionError(impossible); 375 } 376 } 377 378 /** 379 * @see #setLogEscapedVariables 380 */ 381 public boolean getLogEscapedVariables() { 382 return logEscapedVariables; 383 } 384 385 /** 386 * Use this method to enable logging of all variables whose values are modified by auto escaping 387 * or <cs escape> commands. These will be logged at {@code Level.WARNING}. This is useful 388 * for detecting variables that should be exempt from auto escaping. 389 * 390 * <p> 391 * It is recommended to only enable this flag during testing or debugging and not for production 392 * jobs. 393 * 394 * @see #setEscapeMode 395 */ 396 public JSilverOptions setLogEscapedVariables(boolean logEscapedVariables) { 397 this.logEscapedVariables = logEscapedVariables; 398 return this; 399 } 400 } 401