All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jetbrick.template.JetEngineImpl Maven / Gradle / Ivy

There is a newer version: 2.1.10
Show newest version
/**
 * Copyright 2013-2016 Guoqiang Chen, Shanghai, China. All rights reserved.
 *
 *   Author: Guoqiang Chen
 *    Email: [email protected]
 *   WebURL: https://github.com/subchen
 *
 * Licensed 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 jetbrick.template;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import jetbrick.io.resource.Resource;
import jetbrick.io.resource.ResourceNotFoundException;
import jetbrick.template.loader.ResourceLoader;
import jetbrick.template.loader.resource.SourceResource;
import jetbrick.template.parser.Symbols;
import jetbrick.template.resolver.GlobalResolver;
import jetbrick.template.runtime.JetForIterator;
import jetbrick.template.runtime.buildin.*;
import jetbrick.util.PathUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 默认的模板引擎实现.(用户不可自己访问,由 JetEngine.create() 创建)
 */
final class JetEngineImpl extends JetEngine {
    private final Logger log = LoggerFactory.getLogger(JetEngineImpl.class);

    // 模板对象缓存
    private final ConcurrentMap cache = new ConcurrentHashMap(128);

    private final JetConfig config;
    private final List loaders; // 全局的资源载入器
    private final JetGlobalContext globalContext; // 全局变量
    private final GlobalResolver globalResolver;

    public JetEngineImpl(JetConfig config) {
        this.config = config;
        this.loaders = config.getTemplateLoaders();

        // output log
        log.info("JetEngine.version = {}", JetEngine.VERSION);
        for (ResourceLoader loader : loaders) {
            log.info("JetEngine.loader = {}, root = {}, reload = {}", loader.getClass().getName(), loader.getRoot(), loader.isReloadable());
        }

        // create globals
        this.globalResolver = doCreateGlobalResolver();
        this.globalContext = doCreateGlobalContext();

        // load global macros
        doLoadGlobalMacroFiles();
    }

    @Override
    public JetConfig getConfig() {
        return config;
    }

    @Override
    public JetGlobalContext getGlobalContext() {
        return globalContext;
    }

    @Override
    public GlobalResolver getGlobalResolver() {
        return globalResolver;
    }

    @Override
    public boolean checkTemplate(String name) {
        return internalGetTemplate(name) != null;
    }

    @Override
    public JetTemplate getTemplate(String name) throws ResourceNotFoundException {
        JetTemplate template = internalGetTemplate(name);
        if (template != null) {
            try {
                template.reload();
                return template;
            } catch (ResourceNotFoundException e) {
                cache.remove(template.getName());
                throw e;
            }
        }
        throw new ResourceNotFoundException(name);
    }

    @Override
    public JetTemplate createTemplate(String source) {
        return createTemplate(SourceResource.DEFAULT_NAME, source);
    }

    @Override
    public JetTemplate createTemplate(String name, String source) {
        Resource resource = new SourceResource(name, source);
        JetTemplate template = new JetTemplateImpl(this, resource, false, config.getTemplateSecurityManager());
        template.reload(); // 开始加载
        return template;
    }

    private JetTemplate internalGetTemplate(String name) {
        // 将一个模板路径名称转为标准格式
        name = PathUtils.normalize(name);
        if (name.startsWith("../")) {
            return null;
        }

        JetTemplate template = cache.get(name);
        if (template != null) {
            return template;
        }

        for (ResourceLoader loader : loaders) {
            Resource resource = loader.load(name);
            if (resource != null) {
                // create a new template
                template = new JetTemplateImpl(this, resource, loader.isReloadable(), loader.getSecurityManager());
                JetTemplate old = cache.putIfAbsent(name, template);
                if (old != null) {
                    template = old;
                }
                return template;
            }
        }

        return null;
    }

    @Override
    public Resource getResource(String name) throws ResourceNotFoundException {
        // 将一个路径名称转为标准格式
        name = PathUtils.normalize(name);
        if (name.startsWith("../")) {
            throw new ResourceNotFoundException(name);
        }

        for (ResourceLoader loader : loaders) {
            Resource resource = loader.load(name);
            if (resource != null) {
                return resource;
            }
        }
        throw new ResourceNotFoundException(name);
    }

    private GlobalResolver doCreateGlobalResolver() {
        log.debug("Initializing global resolver ...");
        GlobalResolver resolver = new GlobalResolver();

        resolver.importClass("java.lang.*");
        resolver.importClass("java.util.*");
        for (String className : config.getImportClasses()) {
            resolver.importClass(className);
        }

        resolver.registerMethods(JetMethods.class);
        for (String className : config.getImportMethods()) {
            resolver.registerMethods(className);
        }

        resolver.registerFunctions(JetFunctions.class);
        for (String className : config.getImportFunctions()) {
            resolver.registerFunctions(className);
        }

        resolver.registerTags(JetTags.class);
        for (String className : config.getImportTags()) {
            resolver.registerTags(className);
        }

        List packageNames = config.getAutoscanPackages();
        if (!packageNames.isEmpty()) {
            resolver.scan(packageNames, config.isAutoscanSkiperrors());
        }

        return resolver;
    }

    private JetGlobalContext doCreateGlobalContext() {
        log.debug("Initializing global context ...");
        JetGlobalContext ctx = new JetGlobalContext();

        ctx.define(JetForIterator.class, Symbols.FOR);

        for (String define : config.getImportDefines()) {
            int pos = define.indexOf(' ');
            String type = define.substring(0, pos);
            String name = define.substring(pos + 1);

            Class cls = globalResolver.resolveClass(type);
            ctx.define(cls, name);
        }

        return ctx;
    }

    private void doLoadGlobalMacroFiles() {
        List macroFiles = config.getImportMacros();
        for (String file : macroFiles) {
            JetTemplate template = getTemplate(file);
            globalResolver.registerMacros(template);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy