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

import freemarker.template.utility.NullArgumentException;
import freemarker.template.utility.StringUtil;

A TemplateLoader that can load templates from the "classpath". Naturally, it can load from jar files, or from anywhere where Java can load classes from. Internally, it uses Class.getResource(String) or ClassLoader.getResource(String) to load templates.
/** * A {@link TemplateLoader} that can load templates from the "classpath". Naturally, it can load from jar files, or from * anywhere where Java can load classes from. Internally, it uses {@link Class#getResource(String)} or * {@link ClassLoader#getResource(String)} to load templates. */
public class ClassTemplateLoader extends URLTemplateLoader { private final Class<?> resourceLoaderClass; private final ClassLoader classLoader; private final String basePackagePath;
Creates a template loader that will use the Class.getResource(String) method of its own class to load the resources, and "/" as base package path. This means that that template paths will be resolved relatively the root package of the class hierarchy, so you hardly ever should use this constructor, rather do something like this:
new ClassTemplateLoader(com.example.myapplication.SomeClass.class, "templates")

If you extend this class, then the extending class will be used to load the resources.

Deprecated:It's a confusing constructor, and seldom useful; use ClassTemplateLoader(Class<?>, String) instead.
/** * Creates a template loader that will use the {@link Class#getResource(String)} method of its own class to load the * resources, and {@code "/"} as base package path. This means that that template paths will be resolved relatively * the root package of the class hierarchy, so you hardly ever should use this constructor, rather do something like * this:<br> * {@link #ClassTemplateLoader(Class, String) new ClassTemplateLoader(com.example.myapplication.SomeClass.class, * "templates")} * * <p> * If you extend this class, then the extending class will be used to load the resources. * * @deprecated It's a confusing constructor, and seldom useful; use {@link #ClassTemplateLoader(Class, String)} * instead. */
@Deprecated public ClassTemplateLoader() { this(null, true, null, "/"); }
Creates a template loader that will use the Class.getResource(String) method of the specified class to load the resources, and "" as base package path. This means that template paths will be resolved relatively to the class location, that is, relatively to the directory (package) of the class.
Params:
Deprecated:It's confusing that the base path is ""; use ClassTemplateLoader(Class<?>, String) instead.
/** * Creates a template loader that will use the {@link Class#getResource(String)} method of the specified class to * load the resources, and {@code ""} as base package path. This means that template paths will be resolved * relatively to the class location, that is, relatively to the directory (package) of the class. * * @param resourceLoaderClass * the class whose {@link Class#getResource(String)} will be used to load the templates. * * @deprecated It's confusing that the base path is {@code ""}; use {@link #ClassTemplateLoader(Class, String)} * instead. */
@Deprecated public ClassTemplateLoader(Class<?> resourceLoaderClass) { this(resourceLoaderClass, ""); }
Creates a template loader that will use the Class.getResource(String) method of the specified class to load the resources, and the specified base package path (absolute or relative).

Examples:

  • Relative base path (will load from the com.example.myapplication.templates package):
    new ClassTemplateLoader(com.example.myapplication.SomeClass.class, "templates")
  • Absolute base path:
    new ClassTemplateLoader(somepackage.SomeClass.class, "/com/example/myapplication/templates")
Params:
  • resourceLoaderClass – The class whose Class.getResource(String) method will be used to load the templates. Be sure that you chose a class whose defining class-loader sees the templates. This parameter can't be null.
  • basePackagePath – The package that contains the templates, in path (/-separated) format. If it doesn't start with a / then it's relative to the path (package) of the resourceLoaderClass class. If it starts with / then it's relative to the root of the package hierarchy. Note that path components should be separated by forward slashes independently of the separator character used by the underlying operating system. This parameter can't be null.
See Also:
/** * Creates a template loader that will use the {@link Class#getResource(String)} method of the specified class to * load the resources, and the specified base package path (absolute or relative). * * <p> * Examples: * <ul> * <li>Relative base path (will load from the {@code com.example.myapplication.templates} package):<br> * {@code new ClassTemplateLoader(com.example.myapplication.SomeClass.class, "templates")} * <li>Absolute base path:<br> * {@code new ClassTemplateLoader(somepackage.SomeClass.class, "/com/example/myapplication/templates")} * </ul> * * @param resourceLoaderClass * The class whose {@link Class#getResource(String)} method will be used to load the templates. Be sure * that you chose a class whose defining class-loader sees the templates. This parameter can't be * {@code null}. * @param basePackagePath * The package that contains the templates, in path ({@code /}-separated) format. If it doesn't start * with a {@code /} then it's relative to the path (package) of the {@code resourceLoaderClass} class. If * it starts with {@code /} then it's relative to the root of the package hierarchy. Note that path * components should be separated by forward slashes independently of the separator character used by the * underlying operating system. This parameter can't be {@code null}. * * @see #ClassTemplateLoader(ClassLoader, String) */
public ClassTemplateLoader(Class<?> resourceLoaderClass, String basePackagePath) { this(resourceLoaderClass, false, null, basePackagePath); }
Similar to ClassTemplateLoader(Class<?>, String), but instead of Class.getResource(String) it uses ClassLoader.getResource(String). Because a ClassLoader isn't bound to any Java package, it doesn't mater if the basePackagePath starts with / or not, it will be always relative to the root of the package hierarchy
Since:2.3.22
/** * Similar to {@link #ClassTemplateLoader(Class, String)}, but instead of {@link Class#getResource(String)} it uses * {@link ClassLoader#getResource(String)}. Because a {@link ClassLoader} isn't bound to any Java package, it * doesn't mater if the {@code basePackagePath} starts with {@code /} or not, it will be always relative to the root * of the package hierarchy * * @since 2.3.22 */
public ClassTemplateLoader(ClassLoader classLoader, String basePackagePath) { this(null, true, classLoader, basePackagePath); } private ClassTemplateLoader(Class<?> resourceLoaderClass, boolean allowNullResourceLoaderClass, ClassLoader classLoader, String basePackagePath) { if (!allowNullResourceLoaderClass) { NullArgumentException.check("resourceLoaderClass", resourceLoaderClass); } NullArgumentException.check("basePackagePath", basePackagePath); // Either set a non-null resourceLoaderClass or a non-null classLoader, not both: this.resourceLoaderClass = classLoader == null ? (resourceLoaderClass == null ? this.getClass() : resourceLoaderClass) : null; if (this.resourceLoaderClass == null && classLoader == null) { throw new NullArgumentException("classLoader"); } this.classLoader = classLoader; String canonBasePackagePath = canonicalizePrefix(basePackagePath); if (this.classLoader != null && canonBasePackagePath.startsWith("/")) { canonBasePackagePath = canonBasePackagePath.substring(1); } this.basePackagePath = canonBasePackagePath; } @Override protected URL getURL(String name) { String fullPath = basePackagePath + name; // Block java.net.URLClassLoader exploits: if (basePackagePath.equals("/") && !isSchemeless(fullPath)) { return null; } return resourceLoaderClass != null ? resourceLoaderClass.getResource(fullPath) : classLoader .getResource(fullPath); } private static boolean isSchemeless(String fullPath) { int i = 0; int ln = fullPath.length(); // Skip a single initial /, as things like "/file:/..." might work: if (i < ln && fullPath.charAt(i) == '/') i++; // Check if there's no ":" earlier than a '/', as the URLClassLoader // could interpret that as an URL scheme: while (i < ln) { char c = fullPath.charAt(i); if (c == '/') return true; if (c == ':') return false; i++; } return true; }
Show class name and some details that are useful in template-not-found errors.
Since:2.3.21
/** * Show class name and some details that are useful in template-not-found errors. * * @since 2.3.21 */
@Override public String toString() { return TemplateLoaderUtils.getClassNameForToString(this) + "(" + (resourceLoaderClass != null ? "resourceLoaderClass=" + resourceLoaderClass.getName() : "classLoader=" + StringUtil.jQuote(classLoader)) + ", basePackagePath" + "=" + StringUtil.jQuote(basePackagePath) + (resourceLoaderClass != null ? (basePackagePath.startsWith("/") ? "" : " /* relatively to resourceLoaderClass pkg */") : "" ) + ")"; }
See the similar parameter of ClassTemplateLoader(Class<?>, String); null when other mechanism is used to load the resources.
Since:2.3.22
/** * See the similar parameter of {@link #ClassTemplateLoader(Class, String)}; {@code null} when other mechanism is * used to load the resources. * * @since 2.3.22 */
public Class getResourceLoaderClass() { return resourceLoaderClass; }
See the similar parameter of ClassTemplateLoader(ClassLoader, String); null when other mechanism is used to load the resources.
Since:2.3.22
/** * See the similar parameter of {@link #ClassTemplateLoader(ClassLoader, String)}; {@code null} when other mechanism * is used to load the resources. * * @since 2.3.22 */
public ClassLoader getClassLoader() { return classLoader; }
See the similar parameter of ClassTemplateLoader(ClassLoader, String); note that this is a normalized version of what was actually passed to the constructor.
Since:2.3.22
/** * See the similar parameter of {@link #ClassTemplateLoader(ClassLoader, String)}; note that this is a normalized * version of what was actually passed to the constructor. * * @since 2.3.22 */
public String getBasePackagePath() { return basePackagePath; } }