Home | History | Annotate | Download | only in jsilver
      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 &lt;cs escape&gt; 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 &lt;cs set&gt; or &lt;cs
    232    * call&gt; 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 &lt;cs escape&gt; 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