| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package freemarker.cache; |
| |
| import java.io.IOException; |
| import java.util.Locale; |
| |
| import freemarker.template.Configuration; |
| import freemarker.template.Template; |
| |
| /** |
| * Finds the {@link TemplateLoader}-level (storage-level) template source for the template name with which the template |
| * was requested (as in {@link Configuration#getTemplate(String)}). This usually means trying various |
| * {@link TemplateLoader}-level template names (so called source names; see also {@link Template#getSourceName()}) that |
| * were deduced from the requested name. Trying a name usually means calling |
| * {@link TemplateLookupContext#lookupWithAcquisitionStrategy(String)} with it and checking the value of |
| * {@link TemplateLookupResult#isPositive()}. |
| * |
| * <p> |
| * Before you write your own lookup strategy, know that: |
| * <ul> |
| * <li>A template lookup strategy meant to operate solely with template names, not with {@link TemplateLoader}-s |
| * directly. Basically, it's a mapping between the template names that templates and API-s like |
| * {@link Configuration#getTemplate(String)} see, and those that the underlying {@link TemplateLoader} sees. |
| * <li>A template lookup strategy doesn't influence the template's name ({@link Template#getName()}), which is the |
| * normalized form of the template name as it was requested (with {@link Configuration#getTemplate(String)}, etc.). It |
| * only influences the so called source name of the template ({@link Template#getSourceName()}). The template's name is |
| * used as the basis for resolving relative inclusions/imports in the template. The source name is pretty much only used |
| * in error messages as error location, and of course, to actually load the template "file". |
| * <li>Understand the impact of the last point if your template lookup strategy fiddles not only with the file name part |
| * of the template name, but also with the directory part. For example, one may want to map "foo.ftl" to "en/foo.ftl", |
| * "fr/foo.ftl", etc. That's legal, but the result is kind of like if you had several root directories ("en/", "fr/", |
| * etc.) that are layered over each other to form a single merged directory. (This is what's desirable in typical |
| * applications, yet it can be confusing.) |
| * </ul> |
| * |
| * @see Configuration#setTemplateLookupStrategy(TemplateLookupStrategy) |
| * |
| * @since 2.3.22 |
| */ |
| public abstract class TemplateLookupStrategy { |
| |
| /** |
| * <p> |
| * The default lookup strategy of FreeMarker. |
| * |
| * <p> |
| * Through an example: Assuming localized lookup is enabled and that a template is requested for the name |
| * {@code example.ftl} and {@code Locale("es", "ES", "Traditional_WIN")}, it will try the following template names, |
| * in this order: {@code "foo_en_AU_Traditional_WIN.ftl"}, {@code "foo_en_AU_Traditional.ftl"}, |
| * {@code "foo_en_AU.ftl"}, {@code "foo_en.ftl"}, {@code "foo.ftl"}. It stops at the first variation where it finds |
| * a template. (If the template name contains "*" steps, finding the template for the attempted localized variation |
| * happens with the template acquisition mechanism.) If localized lookup is disabled, it won't try to add any locale |
| * strings, so it just looks for {@code "foo.ftl"}. |
| * |
| * <p> |
| * The generation of the localized name variation with the default lookup strategy, happens like this: It removes |
| * the file extension (the part starting with the <em>last</em> dot), then appends {@link Locale#toString()} after |
| * it, and puts back the extension. Then it starts to remove the parts from the end of the locale, considering |
| * {@code "_"} as the separator between the parts. It won't remove parts that are not part of the locale string |
| * (like if the requested template name is {@code foo_bar.ftl}, it won't remove the {@code "_bar"}). |
| */ |
| public static final TemplateLookupStrategy DEFAULT_2_3_0 = new Default020300(); |
| |
| /** |
| * Finds the template source that matches the template name, locale (if not {@code null}) and other parameters |
| * specified in the {@link TemplateLookupContext}. See also the class-level {@link TemplateLookupStrategy} |
| * documentation to understand lookup strategies more. |
| * |
| * @param ctx |
| * Contains the parameters for which the matching template need to be found, and operations that |
| * are needed to implement the strategy. Some of the important input parameters are: |
| * {@link TemplateLookupContext#getTemplateName()}, {@link TemplateLookupContext#getTemplateLocale()}. |
| * The most important operations are {@link TemplateLookupContext#lookupWithAcquisitionStrategy(String)} |
| * and {@link TemplateLookupContext#createNegativeLookupResult()}. (Note that you deliberately can't |
| * use {@link TemplateLoader}-s directly to implement lookup.) |
| * |
| * @return Usually the return value of {@link TemplateLookupContext#lookupWithAcquisitionStrategy(String)}, or |
| * {@code TemplateLookupContext#createNegativeLookupResult()} if no matching template exists. Can't be |
| * {@code null}. |
| */ |
| public abstract TemplateLookupResult lookup(TemplateLookupContext ctx) throws IOException; |
| |
| private static class Default020300 extends TemplateLookupStrategy { |
| |
| @Override |
| public TemplateLookupResult lookup(TemplateLookupContext ctx) throws IOException { |
| return ctx.lookupWithLocalizedThenAcquisitionStrategy(ctx.getTemplateName(), ctx.getTemplateLocale()); |
| } |
| |
| @Override |
| public String toString() { |
| return "TemplateLookupStrategy.DEFAULT_2_3_0"; |
| } |
| |
| } |
| |
| } |