001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.ui.freemarker;
018
019import java.io.IOException;
020import java.io.InputStreamReader;
021import java.io.Reader;
022
023import freemarker.cache.TemplateLoader;
024import org.apache.commons.logging.Log;
025import org.apache.commons.logging.LogFactory;
026
027import org.springframework.core.io.Resource;
028import org.springframework.core.io.ResourceLoader;
029import org.springframework.lang.Nullable;
030
031/**
032 * FreeMarker {@link TemplateLoader} adapter that loads via a Spring {@link ResourceLoader}.
033 * Used by {@link FreeMarkerConfigurationFactory} for any resource loader path that cannot
034 * be resolved to a {@link java.io.File}.
035 *
036 * @author Juergen Hoeller
037 * @since 14.03.2004
038 * @see FreeMarkerConfigurationFactory#setTemplateLoaderPath
039 * @see freemarker.template.Configuration#setDirectoryForTemplateLoading
040 */
041public class SpringTemplateLoader implements TemplateLoader {
042
043        protected final Log logger = LogFactory.getLog(getClass());
044
045        private final ResourceLoader resourceLoader;
046
047        private final String templateLoaderPath;
048
049
050        /**
051         * Create a new SpringTemplateLoader.
052         * @param resourceLoader the Spring ResourceLoader to use
053         * @param templateLoaderPath the template loader path to use
054         */
055        public SpringTemplateLoader(ResourceLoader resourceLoader, String templateLoaderPath) {
056                this.resourceLoader = resourceLoader;
057                if (!templateLoaderPath.endsWith("/")) {
058                        templateLoaderPath += "/";
059                }
060                this.templateLoaderPath = templateLoaderPath;
061                if (logger.isDebugEnabled()) {
062                        logger.debug("SpringTemplateLoader for FreeMarker: using resource loader [" + this.resourceLoader +
063                                        "] and template loader path [" + this.templateLoaderPath + "]");
064                }
065        }
066
067
068        @Override
069        @Nullable
070        public Object findTemplateSource(String name) throws IOException {
071                if (logger.isDebugEnabled()) {
072                        logger.debug("Looking for FreeMarker template with name [" + name + "]");
073                }
074                Resource resource = this.resourceLoader.getResource(this.templateLoaderPath + name);
075                return (resource.exists() ? resource : null);
076        }
077
078        @Override
079        public Reader getReader(Object templateSource, String encoding) throws IOException {
080                Resource resource = (Resource) templateSource;
081                try {
082                        return new InputStreamReader(resource.getInputStream(), encoding);
083                }
084                catch (IOException ex) {
085                        if (logger.isDebugEnabled()) {
086                                logger.debug("Could not find FreeMarker template: " + resource);
087                        }
088                        throw ex;
089                }
090        }
091
092        @Override
093        public long getLastModified(Object templateSource) {
094                Resource resource = (Resource) templateSource;
095                try {
096                        return resource.lastModified();
097                }
098                catch (IOException ex) {
099                        if (logger.isDebugEnabled()) {
100                                logger.debug("Could not obtain last-modified timestamp for FreeMarker template in " +
101                                                resource + ": " + ex);
102                        }
103                        return -1;
104                }
105        }
106
107        @Override
108        public void closeTemplateSource(Object templateSource) throws IOException {
109        }
110
111}