/*
 * 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.core;

import java.io.Writer;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template._TemplateAPI;
import freemarker.template.utility.ClassUtil;


For internal use only; don't depend on this, there's no backward compatibility guarantee at all! This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can access things inside this package that users shouldn't.
/** * For internal use only; don't depend on this, there's no backward compatibility guarantee at all! * This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can * access things inside this package that users shouldn't. */
public class _CoreAPI { public static final String ERROR_MESSAGE_HR = "----"; // Can't be instantiated private _CoreAPI() { } private static void addName(Set<String> allNames, Set<String> lcNames, Set<String> ccNames, String commonName) { allNames.add(commonName); lcNames.add(commonName); ccNames.add(commonName); } private static void addName(Set<String> allNames, Set<String> lcNames, Set<String> ccNames, String lcName, String ccName) { allNames.add(lcName); allNames.add(ccName); lcNames.add(lcName); ccNames.add(ccName); } public static final Set<String> ALL_BUILT_IN_DIRECTIVE_NAMES; public static final Set<String> LEGACY_BUILT_IN_DIRECTIVE_NAMES; public static final Set<String> CAMEL_CASE_BUILT_IN_DIRECTIVE_NAMES; static { Set<String> allNames = new TreeSet(); Set<String> lcNames = new TreeSet(); Set<String> ccNames = new TreeSet(); addName(allNames, lcNames, ccNames, "assign"); addName(allNames, lcNames, ccNames, "attempt"); addName(allNames, lcNames, ccNames, "autoesc", "autoEsc"); addName(allNames, lcNames, ccNames, "break"); addName(allNames, lcNames, ccNames, "call"); addName(allNames, lcNames, ccNames, "case"); addName(allNames, lcNames, ccNames, "comment"); addName(allNames, lcNames, ccNames, "compress"); addName(allNames, lcNames, ccNames, "continue"); addName(allNames, lcNames, ccNames, "default"); addName(allNames, lcNames, ccNames, "else"); addName(allNames, lcNames, ccNames, "elseif", "elseIf"); addName(allNames, lcNames, ccNames, "escape"); addName(allNames, lcNames, ccNames, "fallback"); addName(allNames, lcNames, ccNames, "flush"); addName(allNames, lcNames, ccNames, "foreach", "forEach"); addName(allNames, lcNames, ccNames, "ftl"); addName(allNames, lcNames, ccNames, "function"); addName(allNames, lcNames, ccNames, "global"); addName(allNames, lcNames, ccNames, "if"); addName(allNames, lcNames, ccNames, "import"); addName(allNames, lcNames, ccNames, "include"); addName(allNames, lcNames, ccNames, "items"); addName(allNames, lcNames, ccNames, "list"); addName(allNames, lcNames, ccNames, "local"); addName(allNames, lcNames, ccNames, "lt"); addName(allNames, lcNames, ccNames, "macro"); addName(allNames, lcNames, ccNames, "nested"); addName(allNames, lcNames, ccNames, "noautoesc", "noAutoEsc"); addName(allNames, lcNames, ccNames, "noescape", "noEscape"); addName(allNames, lcNames, ccNames, "noparse", "noParse"); addName(allNames, lcNames, ccNames, "nt"); addName(allNames, lcNames, ccNames, "outputformat", "outputFormat"); addName(allNames, lcNames, ccNames, "recover"); addName(allNames, lcNames, ccNames, "recurse"); addName(allNames, lcNames, ccNames, "return"); addName(allNames, lcNames, ccNames, "rt"); addName(allNames, lcNames, ccNames, "sep"); addName(allNames, lcNames, ccNames, "setting"); addName(allNames, lcNames, ccNames, "stop"); addName(allNames, lcNames, ccNames, "switch"); addName(allNames, lcNames, ccNames, "t"); addName(allNames, lcNames, ccNames, "transform"); addName(allNames, lcNames, ccNames, "visit"); ALL_BUILT_IN_DIRECTIVE_NAMES = Collections.unmodifiableSet(allNames); LEGACY_BUILT_IN_DIRECTIVE_NAMES = Collections.unmodifiableSet(lcNames); CAMEL_CASE_BUILT_IN_DIRECTIVE_NAMES = Collections.unmodifiableSet(ccNames); }
Returns the names of the currently supported "built-ins" (expr?builtin_name-like things).
Params:
/** * Returns the names of the currently supported "built-ins" ({@code expr?builtin_name}-like things). * * @param namingConvention * One of {@link Configuration#AUTO_DETECT_NAMING_CONVENTION}, * {@link Configuration#LEGACY_NAMING_CONVENTION}, and * {@link Configuration#CAMEL_CASE_NAMING_CONVENTION}. If it's * {@link Configuration#AUTO_DETECT_NAMING_CONVENTION} then the union of the names in all the naming * conventions is returned. */
public static Set<String> getSupportedBuiltInNames(int namingConvention) { Set<String> names; if (namingConvention == Configuration.AUTO_DETECT_NAMING_CONVENTION) { names = BuiltIn.BUILT_INS_BY_NAME.keySet(); } else if (namingConvention == Configuration.LEGACY_NAMING_CONVENTION) { names = BuiltIn.SNAKE_CASE_NAMES; } else if (namingConvention == Configuration.CAMEL_CASE_NAMING_CONVENTION) { names = BuiltIn.CAMEL_CASE_NAMES; } else { throw new IllegalArgumentException("Unsupported naming convention constant: " + namingConvention); } return Collections.unmodifiableSet(names); } public static void appendInstructionStackItem(TemplateElement stackEl, StringBuilder sb) { Environment.appendInstructionStackItem(stackEl, sb); } public static TemplateElement[] getInstructionStackSnapshot(Environment env) { return env.getInstructionStackSnapshot(); } public static void outputInstructionStack( TemplateElement[] instructionStackSnapshot, boolean terseMode, Writer pw) { Environment.outputInstructionStack(instructionStackSnapshot, terseMode, pw); }
ATTENTION: This is used by https://github.com/kenshoo/freemarker-online. Don't break backward compatibility without updating that project too!
/** * ATTENTION: This is used by https://github.com/kenshoo/freemarker-online. Don't break backward * compatibility without updating that project too! */
static final public void addThreadInterruptedChecks(Template template) { try { new ThreadInterruptionSupportTemplatePostProcessor().postProcess(template); } catch (TemplatePostProcessorException e) { throw new RuntimeException("Template post-processing failed", e); } } static final public void checkHasNoNestedContent(TemplateDirectiveBody body) throws NestedContentNotSupportedException { NestedContentNotSupportedException.check(body); } static final public void replaceText(TextBlock textBlock, String text) { textBlock.replaceText(text); }
Throws:
  • IllegalArgumentException – if the type of the some of the values isn't as expected
/** * @throws IllegalArgumentException * if the type of the some of the values isn't as expected */
public static void checkSettingValueItemsType(String somethingsSentenceStart, Class<?> expectedClass, Collection<?> values) { if (values == null) return; for (Object value : values) { if (!expectedClass.isInstance(value)) { throw new IllegalArgumentException(somethingsSentenceStart + " must be instances of " + ClassUtil.getShortClassName(expectedClass) + ", but one of them was a(n) " + ClassUtil.getShortClassNameOfObject(value) + "."); } } }
The work around the problematic cases where we should throw a TemplateException, but we are inside a TemplateModel method and so we can only throw TemplateModelException-s.
/** * The work around the problematic cases where we should throw a {@link TemplateException}, but we are inside * a {@link TemplateModel} method and so we can only throw {@link TemplateModelException}-s. */
public static TemplateModelException ensureIsTemplateModelException(String modelOpMsg, TemplateException e) { if (e instanceof TemplateModelException) { return (TemplateModelException) e; } else { return new _TemplateModelException( _TemplateAPI.getBlamedExpression(e), e.getCause(), e.getEnvironment(), modelOpMsg); } } public static TemplateElement getParentElement(TemplateElement te) { return te.getParentElement(); } public static TemplateElement getChildElement(TemplateElement te, int index) { return te.getChild(index); } public static void setPreventStrippings(FMParser parser, boolean preventStrippings) { parser.setPreventStrippings(preventStrippings); } }