use of freemarker.cache.TemplateLookupStrategy in project freemarker by apache.
the class Configuration method setSetting.
@Override
public void setSetting(String name, String value) throws TemplateException {
boolean unknown = false;
try {
if ("TemplateUpdateInterval".equalsIgnoreCase(name)) {
name = TEMPLATE_UPDATE_DELAY_KEY;
} else if ("DefaultEncoding".equalsIgnoreCase(name)) {
name = DEFAULT_ENCODING_KEY;
}
if (DEFAULT_ENCODING_KEY_SNAKE_CASE.equals(name) || DEFAULT_ENCODING_KEY_CAMEL_CASE.equals(name)) {
if (JVM_DEFAULT.equalsIgnoreCase(value)) {
setDefaultEncoding(getJVMDefaultEncoding());
} else {
setDefaultEncoding(value);
}
} else if (LOCALIZED_LOOKUP_KEY_SNAKE_CASE.equals(name) || LOCALIZED_LOOKUP_KEY_CAMEL_CASE.equals(name)) {
setLocalizedLookup(StringUtil.getYesNo(value));
} else if (STRICT_SYNTAX_KEY_SNAKE_CASE.equals(name) || STRICT_SYNTAX_KEY_CAMEL_CASE.equals(name)) {
setStrictSyntaxMode(StringUtil.getYesNo(value));
} else if (WHITESPACE_STRIPPING_KEY_SNAKE_CASE.equals(name) || WHITESPACE_STRIPPING_KEY_CAMEL_CASE.equals(name)) {
setWhitespaceStripping(StringUtil.getYesNo(value));
} else if (AUTO_ESCAPING_POLICY_KEY_SNAKE_CASE.equals(name) || AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE.equals(name)) {
if ("enable_if_default".equals(value) || "enableIfDefault".equals(value)) {
setAutoEscapingPolicy(ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY);
} else if ("enable_if_supported".equals(value) || "enableIfSupported".equals(value)) {
setAutoEscapingPolicy(ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY);
} else if ("disable".equals(value)) {
setAutoEscapingPolicy(DISABLE_AUTO_ESCAPING_POLICY);
} else {
throw invalidSettingValueException(name, value);
}
} else if (OUTPUT_FORMAT_KEY_SNAKE_CASE.equals(name) || OUTPUT_FORMAT_KEY_CAMEL_CASE.equals(name)) {
if (value.equalsIgnoreCase(DEFAULT)) {
unsetOutputFormat();
} else {
OutputFormat stdOF = STANDARD_OUTPUT_FORMATS.get(value);
setOutputFormat(stdOF != null ? stdOF : (OutputFormat) _ObjectBuilderSettingEvaluator.eval(value, OutputFormat.class, true, _SettingEvaluationEnvironment.getCurrent()));
}
} else if (REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_SNAKE_CASE.equals(name) || REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_CAMEL_CASE.equals(name)) {
List list = (List) _ObjectBuilderSettingEvaluator.eval(value, List.class, true, _SettingEvaluationEnvironment.getCurrent());
for (Object item : list) {
if (!(item instanceof OutputFormat)) {
throw new _MiscTemplateException(getEnvironment(), "Invalid value for setting ", new _DelayedJQuote(name), ": List items must be " + OutputFormat.class.getName() + " instances, in: ", value);
}
}
setRegisteredCustomOutputFormats(list);
} else if (RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE.equals(name) || RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_CAMEL_CASE.equals(name)) {
if (value.equalsIgnoreCase(DEFAULT)) {
unsetRecognizeStandardFileExtensions();
} else {
setRecognizeStandardFileExtensions(StringUtil.getYesNo(value));
}
} else if (CACHE_STORAGE_KEY_SNAKE_CASE.equals(name) || CACHE_STORAGE_KEY_CAMEL_CASE.equals(name)) {
if (value.equalsIgnoreCase(DEFAULT)) {
unsetCacheStorage();
}
if (value.indexOf('.') == -1) {
int strongSize = 0;
int softSize = 0;
Map map = StringUtil.parseNameValuePairList(value, String.valueOf(Integer.MAX_VALUE));
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry ent = (Map.Entry) it.next();
String pname = (String) ent.getKey();
int pvalue;
try {
pvalue = Integer.parseInt((String) ent.getValue());
} catch (NumberFormatException e) {
throw invalidSettingValueException(name, value);
}
if ("soft".equalsIgnoreCase(pname)) {
softSize = pvalue;
} else if ("strong".equalsIgnoreCase(pname)) {
strongSize = pvalue;
} else {
throw invalidSettingValueException(name, value);
}
}
if (softSize == 0 && strongSize == 0) {
throw invalidSettingValueException(name, value);
}
setCacheStorage(new MruCacheStorage(strongSize, softSize));
} else {
setCacheStorage((CacheStorage) _ObjectBuilderSettingEvaluator.eval(value, CacheStorage.class, false, _SettingEvaluationEnvironment.getCurrent()));
}
} else if (TEMPLATE_UPDATE_DELAY_KEY_SNAKE_CASE.equals(name) || TEMPLATE_UPDATE_DELAY_KEY_CAMEL_CASE.equals(name)) {
long multipier;
String valueWithoutUnit;
if (value.endsWith("ms")) {
multipier = 1;
valueWithoutUnit = rightTrim(value.substring(0, value.length() - 2));
} else if (value.endsWith("s")) {
multipier = 1000;
valueWithoutUnit = rightTrim(value.substring(0, value.length() - 1));
} else if (value.endsWith("m")) {
multipier = 1000 * 60;
valueWithoutUnit = rightTrim(value.substring(0, value.length() - 1));
} else if (value.endsWith("h")) {
multipier = 1000 * 60 * 60;
valueWithoutUnit = rightTrim(value.substring(0, value.length() - 1));
} else {
// Default is seconds for backward compatibility
multipier = 1000;
valueWithoutUnit = value;
}
setTemplateUpdateDelayMilliseconds(Integer.parseInt(valueWithoutUnit) * multipier);
} else if (TAG_SYNTAX_KEY_SNAKE_CASE.equals(name) || TAG_SYNTAX_KEY_CAMEL_CASE.equals(name)) {
if ("auto_detect".equals(value) || "autoDetect".equals(value)) {
setTagSyntax(AUTO_DETECT_TAG_SYNTAX);
} else if ("angle_bracket".equals(value) || "angleBracket".equals(value)) {
setTagSyntax(ANGLE_BRACKET_TAG_SYNTAX);
} else if ("square_bracket".equals(value) || "squareBracket".equals(value)) {
setTagSyntax(SQUARE_BRACKET_TAG_SYNTAX);
} else {
throw invalidSettingValueException(name, value);
}
} else if (INTERPOLATION_SYNTAX_KEY_SNAKE_CASE.equals(name) || INTERPOLATION_SYNTAX_KEY_CAMEL_CASE.equals(name)) {
if ("legacy".equals(value)) {
setInterpolationSyntax(LEGACY_INTERPOLATION_SYNTAX);
} else if ("dollar".equals(value)) {
setInterpolationSyntax(DOLLAR_INTERPOLATION_SYNTAX);
} else if ("square_bracket".equals(value) || "squareBracket".equals(value)) {
setInterpolationSyntax(SQUARE_BRACKET_INTERPOLATION_SYNTAX);
} else {
throw invalidSettingValueException(name, value);
}
} else if (NAMING_CONVENTION_KEY_SNAKE_CASE.equals(name) || NAMING_CONVENTION_KEY_CAMEL_CASE.equals(name)) {
if ("auto_detect".equals(value) || "autoDetect".equals(value)) {
setNamingConvention(AUTO_DETECT_NAMING_CONVENTION);
} else if ("legacy".equals(value)) {
setNamingConvention(LEGACY_NAMING_CONVENTION);
} else if ("camel_case".equals(value) || "camelCase".equals(value)) {
setNamingConvention(CAMEL_CASE_NAMING_CONVENTION);
} else {
throw invalidSettingValueException(name, value);
}
} else if (TAB_SIZE_KEY_SNAKE_CASE.equals(name) || TAB_SIZE_KEY_CAMEL_CASE.equals(name)) {
setTabSize(Integer.parseInt(value));
} else if (INCOMPATIBLE_IMPROVEMENTS_KEY_SNAKE_CASE.equals(name) || INCOMPATIBLE_IMPROVEMENTS_KEY_CAMEL_CASE.equals(name)) {
setIncompatibleImprovements(new Version(value));
} else if (INCOMPATIBLE_ENHANCEMENTS.equals(name)) {
setIncompatibleEnhancements(value);
} else if (TEMPLATE_LOADER_KEY_SNAKE_CASE.equals(name) || TEMPLATE_LOADER_KEY_CAMEL_CASE.equals(name)) {
if (value.equalsIgnoreCase(DEFAULT)) {
unsetTemplateLoader();
} else {
setTemplateLoader((TemplateLoader) _ObjectBuilderSettingEvaluator.eval(value, TemplateLoader.class, true, _SettingEvaluationEnvironment.getCurrent()));
}
} else if (TEMPLATE_LOOKUP_STRATEGY_KEY_SNAKE_CASE.equals(name) || TEMPLATE_LOOKUP_STRATEGY_KEY_CAMEL_CASE.equals(name)) {
if (value.equalsIgnoreCase(DEFAULT)) {
unsetTemplateLookupStrategy();
} else {
setTemplateLookupStrategy((TemplateLookupStrategy) _ObjectBuilderSettingEvaluator.eval(value, TemplateLookupStrategy.class, false, _SettingEvaluationEnvironment.getCurrent()));
}
} else if (TEMPLATE_NAME_FORMAT_KEY_SNAKE_CASE.equals(name) || TEMPLATE_NAME_FORMAT_KEY_CAMEL_CASE.equals(name)) {
if (value.equalsIgnoreCase(DEFAULT)) {
unsetTemplateNameFormat();
} else if (value.equalsIgnoreCase("default_2_3_0")) {
setTemplateNameFormat(TemplateNameFormat.DEFAULT_2_3_0);
} else if (value.equalsIgnoreCase("default_2_4_0")) {
setTemplateNameFormat(TemplateNameFormat.DEFAULT_2_4_0);
} else {
throw invalidSettingValueException(name, value);
}
} else if (TEMPLATE_CONFIGURATIONS_KEY_SNAKE_CASE.equals(name) || TEMPLATE_CONFIGURATIONS_KEY_CAMEL_CASE.equals(name)) {
if (value.equals(NULL)) {
setTemplateConfigurations(null);
} else {
setTemplateConfigurations((TemplateConfigurationFactory) _ObjectBuilderSettingEvaluator.eval(value, TemplateConfigurationFactory.class, false, _SettingEvaluationEnvironment.getCurrent()));
}
} else {
unknown = true;
}
} catch (Exception e) {
throw settingValueAssignmentException(name, value, e);
}
if (unknown) {
super.setSetting(name, value);
}
}
use of freemarker.cache.TemplateLookupStrategy in project freemarker by apache.
the class TemplateNotFoundMessageTest method testOtherMessageDetails.
@Test
public void testOtherMessageDetails() throws IOException {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
cfg.setTemplateLoader(new StringTemplateLoader());
{
String errMsg = failWith("../x", cfg);
showErrorMessage(errMsg);
assertThat(errMsg, allOf(containsStringIgnoringCase("reason"), containsStringIgnoringCase("root directory")));
}
{
String errMsg = failWith("x\u0000y", cfg);
showErrorMessage(errMsg);
assertThat(errMsg, allOf(containsStringIgnoringCase("reason"), containsStringIgnoringCase("null character")));
}
{
String errMsg = failWith("x\\y", cfg);
showErrorMessage(errMsg);
assertThat(errMsg, allOf(containsStringIgnoringCase("warning"), containsStringIgnoringCase("backslash")));
}
{
String errMsg = failWith("x/./y", cfg);
showErrorMessage(errMsg);
assertThat(errMsg, allOf(containsStringIgnoringCase("normalized"), containsStringIgnoringCase("x/y")));
}
{
String errMsg = failWith("/x/y", cfg);
showErrorMessage(errMsg);
assertThat(errMsg, not(containsStringIgnoringCase("normalized")));
}
{
String errMsg = failWith("x/y", cfg);
showErrorMessage(errMsg);
assertThat(errMsg, not(containsStringIgnoringCase("normalized")));
assertThat(errMsg, not(containsStringIgnoringCase("lookup strategy")));
}
cfg.setTemplateLookupStrategy(new TemplateLookupStrategy() {
@Override
public TemplateLookupResult lookup(TemplateLookupContext ctx) throws IOException {
return ctx.lookupWithAcquisitionStrategy(ctx.getTemplateName());
}
});
{
String errMsg = failWith("x/y", cfg);
showErrorMessage(errMsg);
assertThat(errMsg, containsStringIgnoringCase("lookup strategy"));
}
try {
cfg.getTemplate("./missing", null, "example.com", null, true, false);
fail();
} catch (TemplateNotFoundException e) {
showErrorMessage(e.getMessage());
assertThat(e.getMessage(), containsStringIgnoringCase("example.com"));
}
}
use of freemarker.cache.TemplateLookupStrategy in project freemarker by apache.
the class ConfigurationTest method testTemplateLookupStrategyDefaultAndSet.
public void testTemplateLookupStrategyDefaultAndSet() throws IOException {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
assertSame(TemplateLookupStrategy.DEFAULT_2_3_0, cfg.getTemplateLookupStrategy());
cfg.setClassForTemplateLoading(ConfigurationTest.class, "");
assertSame(TemplateLookupStrategy.DEFAULT_2_3_0, cfg.getTemplateLookupStrategy());
CacheStorageWithGetSize cache = (CacheStorageWithGetSize) cfg.getCacheStorage();
cfg.setClassForTemplateLoading(ConfigurationTest.class, "");
assertEquals(0, cache.getSize());
cfg.getTemplate("toCache1.ftl");
assertEquals(1, cache.getSize());
cfg.setTemplateLookupStrategy(TemplateLookupStrategy.DEFAULT_2_3_0);
assertEquals(1, cache.getSize());
final TemplateLookupStrategy myStrategy = new TemplateLookupStrategy() {
@Override
public TemplateLookupResult lookup(TemplateLookupContext ctx) throws IOException {
return ctx.lookupWithAcquisitionStrategy(ctx.getTemplateName());
}
};
cfg.setTemplateLookupStrategy(myStrategy);
assertEquals(0, cache.getSize());
assertSame(myStrategy, cfg.getTemplateLookupStrategy());
cfg.getTemplate("toCache1.ftl");
assertEquals(1, cache.getSize());
cfg.setTemplateLookupStrategy(myStrategy);
assertEquals(1, cache.getSize());
cfg.setTemplateLookupStrategy(TemplateLookupStrategy.DEFAULT_2_3_0);
assertEquals(0, cache.getSize());
}
use of freemarker.cache.TemplateLookupStrategy in project freemarker by apache.
the class Configuration method getTemplate.
/**
* Retrieves the template with the given name (and according the specified further parameters) from the template
* cache, loading it into the cache first if it's missing/staled.
*
* <p>
* This method is thread-safe.
*
* <p>
* See {@link Configuration} for an example of basic usage.
*
* @param name
* The name or path of the template, which is not a real path, but interpreted inside the current
* {@link TemplateLoader}. Can't be {@code null}. The exact syntax of the name depends on the underlying
* {@link TemplateLoader}, but the cache makes some assumptions. First, the name is expected to be a
* hierarchical path, with path components separated by a slash character (not with backslash!). The path
* (the name) given here must <em>not</em> begin with slash; it's always interpreted relative to the
* "template root directory". Then, the {@code ..} and {@code .} path meta-elements will be resolved. For
* example, if the name is {@code a/../b/./c.ftl}, then it will be simplified to {@code b/c.ftl}. The
* rules regarding this are the same as with conventional UN*X paths. The path must not reach outside the
* template root directory, that is, it can't be something like {@code "../templates/my.ftl"} (not even
* if this path happens to be equivalent with {@code "/my.ftl"}). Furthermore, the path is allowed to
* contain at most one path element whose name is {@code *} (asterisk). This path meta-element triggers
* the <i>acquisition mechanism</i>. If the template is not found in the location described by the
* concatenation of the path left to the asterisk (called base path) and the part to the right of the
* asterisk (called resource path), the cache will attempt to remove the rightmost path component from
* the base path ("go up one directory") and concatenate that with the resource path. The process is
* repeated until either a template is found, or the base path is completely exhausted.
*
* @param locale
* The requested locale of the template. This is what {@link Template#getLocale()} on the resulting
* {@link Template} will return (unless it's overridden via {@link #getTemplateConfigurations()}). This
* parameter can be {@code null} since 2.3.22, in which case it defaults to
* {@link Configuration#getLocale()} (note that {@link Template#getLocale()} will give the default value,
* not {@code null}). This parameter also drives localized template lookup. Assuming that you have
* specified {@code en_US} as the locale and {@code myTemplate.ftl} as the name of the template, and the
* default {@link TemplateLookupStrategy} is used and
* {@code #setLocalizedLookup(boolean) localized_lookup} is {@code true}, FreeMarker will first try to
* retrieve {@code myTemplate_en_US.html}, then {@code myTemplate.en.ftl}, and finally
* {@code myTemplate.ftl}. Note that that the template's locale will be {@code en_US} even if it only
* finds {@code myTemplate.ftl}. Note that when the {@code locale} setting is overridden with a
* {@link TemplateConfiguration} provided by {@link #getTemplateConfigurations()}, that overrides the
* value specified here, but only after the localized lookup, that is, it modifies the template
* found by the localized lookup.
*
* @param customLookupCondition
* This value can be used by a custom {@link TemplateLookupStrategy}; has no effect with the default one.
* Can be {@code null} (though it's up to the custom {@link TemplateLookupStrategy} if it allows that).
* This object will be used as part of the cache key, so it must to have a proper
* {@link Object#equals(Object)} and {@link Object#hashCode()} method. It also should have reasonable
* {@link Object#toString()}, as it's possibly quoted in error messages. The expected type is up to the
* custom {@link TemplateLookupStrategy}. See also:
* {@link TemplateLookupContext#getCustomLookupCondition()}.
*
* @param encoding
* Deprecated mechanism, {@code null} is the recommended; the charset used to interpret the template
* source code bytes (if it's read from a binary source). Can be {@code null} since 2.3.22, in which case
* it will default to {@link Configuration#getEncoding(Locale)} where {@code Locale} is the
* {@code locale} parameter (when {@code locale} was {@code null} too, the its default value is used
* instead). Why is this deprecated: It doesn't make sense to get the <em>same</em> template with
* different encodings, hence, it's error prone to specify the encoding where you get the template.
* Instead, if you have template "files" with different charsets, you should use
* {@link #setTemplateConfigurations(TemplateConfigurationFactory)}, where you can associate encodings to
* individual templates based on their names (like which "directory" are they in, what's their file
* extension, etc.). The encoding associated with the templates that way overrides the encoding that you
* specify here.
*
* @param parseAsFTL
* If {@code true}, the loaded template is parsed and interpreted normally, as a regular FreeMarker
* template. If {@code false}, the loaded template is treated as a static text, so <code>${...}</code>,
* {@code <#...>} etc. will not have special meaning in it.
*
* @param ignoreMissing
* If {@code true}, the method won't throw {@link TemplateNotFoundException} if the template doesn't
* exist, instead it returns {@code null}. Other kind of exceptions won't be suppressed.
*
* @return the requested template; maybe {@code null} when the {@code ignoreMissing} parameter is {@code true}.
*
* @throws TemplateNotFoundException
* If the template could not be found. Note that this exception extends {@link IOException}.
* @throws MalformedTemplateNameException
* If the template name given was in violation with the {@link TemplateNameFormat} in use. Note that
* this exception extends {@link IOException}.
* @throws ParseException
* (extends <code>IOException</code>) if the template is syntactically bad. Note that this exception
* extends {@link IOException}.
* @throws IOException
* If there was some other problem with reading the template "file". Note that the other exceptions
* extend {@link IOException}, so this should be catched the last.
*
* @since 2.3.22
*/
public Template getTemplate(String name, Locale locale, Object customLookupCondition, String encoding, boolean parseAsFTL, boolean ignoreMissing) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {
if (locale == null) {
locale = getLocale();
}
if (encoding == null) {
encoding = getEncoding(locale);
}
final MaybeMissingTemplate maybeTemp = cache.getTemplate(name, locale, customLookupCondition, encoding, parseAsFTL);
final Template temp = maybeTemp.getTemplate();
if (temp == null) {
if (ignoreMissing) {
return null;
}
TemplateLoader tl = getTemplateLoader();
String msg;
if (tl == null) {
msg = "Don't know where to load template " + StringUtil.jQuote(name) + " from because the \"template_loader\" FreeMarker " + "setting wasn't set (Configuration.setTemplateLoader), so it's null.";
} else {
final String missingTempNormName = maybeTemp.getMissingTemplateNormalizedName();
final String missingTempReason = maybeTemp.getMissingTemplateReason();
final TemplateLookupStrategy templateLookupStrategy = getTemplateLookupStrategy();
msg = "Template not found for name " + StringUtil.jQuote(name) + (missingTempNormName != null && name != null && !removeInitialSlash(name).equals(missingTempNormName) ? " (normalized: " + StringUtil.jQuote(missingTempNormName) + ")" : "") + (customLookupCondition != null ? " and custom lookup condition " + StringUtil.jQuote(customLookupCondition) : "") + "." + (missingTempReason != null ? "\nReason given: " + ensureSentenceIsClosed(missingTempReason) : "") + "\nThe name was interpreted by this TemplateLoader: " + StringUtil.tryToString(tl) + "." + (!isKnownNonConfusingLookupStrategy(templateLookupStrategy) ? "\n(Before that, the name was possibly changed by this lookup strategy: " + StringUtil.tryToString(templateLookupStrategy) + ".)" : "") + // Suspected reasons or warning:
(!templateLoaderExplicitlySet ? "\nWarning: The \"template_loader\" FreeMarker setting " + "wasn't set (Configuration.setTemplateLoader), and using the default value " + "is most certainly not intended and dangerous, and can be the cause of this error." : "") + (missingTempReason == null && name.indexOf('\\') != -1 ? "\nWarning: The name contains backslash (\"\\\") instead of slash (\"/\"); " + "template names should use slash only." : "");
}
String normName = maybeTemp.getMissingTemplateNormalizedName();
throw new TemplateNotFoundException(normName != null ? normName : name, customLookupCondition, msg);
}
return temp;
}
Aggregations