Package jetbrick.template

Source Code of jetbrick.template.JetEngine

/**
* jetbrick-template
* http://subchen.github.io/jetbrick-template/
*
* Copyright 2010-2014 Guoqiang Chen. All rights reserved.
* Email: subchen@gmail.com
*
* 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.io.File;
import java.lang.annotation.Annotation;
import java.util.*;
import jetbrick.template.JetConfig.CompileStrategy;
import jetbrick.template.compiler.JavaCompiler;
import jetbrick.template.compiler.JetTemplateClassLoader;
import jetbrick.template.parser.VariableResolver;
import jetbrick.template.resource.Resource;
import jetbrick.template.resource.SourceCodeResource;
import jetbrick.template.resource.loader.CompiledClassResourceLoader;
import jetbrick.template.resource.loader.ResourceLoader;
import jetbrick.template.utils.*;
import jetbrick.template.utils.finder.AnnotationClassLookupUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JetEngine {
    private static final Logger log = LoggerFactory.getLogger(JetEngine.class);
    public static final String VERSION = Version.getVersion(JetEngine.class);

    private JetConfig config;
    private ResourceLoader resourceLoader;
    private VariableResolver resolver;
    private JetTemplateClassLoader classLoader;
    private ConcurrentResourceCache resourceCache;
    private ConcurrentTemplateCache templateCache;
    private JavaCompiler javaCompiler;
    private JetSecurityManager securityManager;
    private JetGlobalVariables globalVariables;

    public static JetEngine create() {
        return new JetEngine(new JetConfig().loadClasspath(JetConfig.DEFAULT_CONFIG_FILE));
    }

    public static JetEngine create(File configFile) {
        return new JetEngine(new JetConfig().loadFile(configFile));
    }

    public static JetEngine create(Properties properties) {
        return new JetEngine(new JetConfig().load(properties));
    }

    // 提供给 JetWebEngine 用
    protected JetEngine() {
    }

    protected JetEngine(JetConfig config) {
        load(config);
    }

    protected void load(JetConfig config) {
        this.config = config.build();
        this.resolver = createVariableResolver();
        this.resourceLoader = createResourceLoader();
        this.classLoader = new JetTemplateClassLoader(config);
        this.resourceCache = new ConcurrentResourceCache();
        this.templateCache = new ConcurrentTemplateCache();
        this.securityManager = createSecurityManager();
        this.globalVariables = createGlobalVariables();

        if (config.getCompileStrategy() == CompileStrategy.precompile) {
            startPreCompileTask();
        }
    }

    /**
     * 根据一个绝对路径,判断资源文件是否存在.
     */
    public boolean lookupResource(String name) {
        name = PathUtils.getStandardizedName(name);
        return resourceCache.get(name) != null;
    }

    /**
     * 根据一个绝对路径,获取一个资源对象.
     *
     * @throws ResourceNotFoundException
     */
    public Resource getResource(String name) throws ResourceNotFoundException {
        name = PathUtils.getStandardizedName(name);
        Resource resource = resourceCache.get(name);
        if (resource == null) {
            throw new ResourceNotFoundException(name);
        }
        return resource;
    }

    /**
     * 根据一个绝对路径,获取一个模板对象.
     *
     * @throws ResourceNotFoundException
     */
    public JetTemplate getTemplate(String name) throws ResourceNotFoundException {
        name = PathUtils.getStandardizedName(name);
        JetTemplate template = templateCache.get(name);
        template.checkLastModified();
        return template;
    }

    /**
     * 直接从源代码中创建一个新的模板对象.
     *
     * <p>返回的对象内部没有缓存,每次都会重新进行解析和编译,如果需要缓存,请在外面直接实现。</p>
     *
     * @since 1.1.0
     */
    public JetTemplate createTemplate(String source) {
        Resource resource = new SourceCodeResource(source);
        return new JetTemplate(this, resource);
    }

    protected VariableResolver getVariableResolver() {
        return resolver;
    }

    protected JetTemplateClassLoader getClassLoader() {
        return classLoader;
    }

    protected JavaCompiler getJavaCompiler() {
        if (javaCompiler == null) {
            // 在 compileStrategy == none 的情况下,采用延迟加载,可以有效避免没有 javax.tools.JavaCompiler 的情况
            synchronized (this) {
                if (javaCompiler == null) {
                    javaCompiler = JavaCompiler.create(this.classLoader, config);
                }
            }
        }
        return javaCompiler;
    }

    public JetSecurityManager getSecurityManager() {
        return securityManager;
    }

    public JetGlobalVariables getGlobalVariables() {
        return globalVariables;
    }

    /**
     * 获取模板配置.
     */
    public JetConfig getConfig() {
        return config;
    }

    /**
     * 获取模板引擎的版本号.
     */
    public String getVersion() {
        return VERSION;
    }

    private VariableResolver createVariableResolver() {
        VariableResolver resolver = new VariableResolver();
        for (String pkg : config.getImportPackages()) {
            resolver.addImportPackage(pkg);
        }
        for (String klassName : config.getImportClasses()) {
            resolver.addImportClass(klassName);
        }
        for (String method : config.getImportMethods()) {
            resolver.addMethodClass(method);
        }
        for (String function : config.getImportFunctions()) {
            resolver.addFunctionClass(function);
        }
        for (String tag : config.getImportTags()) {
            resolver.addTagClass(tag);
        }
        for (String variable : config.getImportVariables()) {
            int pos = variable.lastIndexOf(" ");
            String defination = variable.substring(0, pos);
            String id = variable.substring(pos + 1);
            resolver.addGlobalVariable(defination, id);
        }

        if (config.isImportAutoscan()) {
            log.info("Starting to autoscan the JetMethods, JetFunctions, JetTags implements...");
            autoScanClassImplements(resolver);
        }

        return resolver;
    }

    // 自动扫描 annotation
    @SuppressWarnings({ "unchecked" })
    private void autoScanClassImplements(VariableResolver resolver) {
        List<String> scanPackages = config.getImportAutoscanPackages();
        //@formatter:off
        Class<? extends Annotation>[] annoClasses = (Class<? extends Annotation>[]) new Class<?>[] {
            JetAnnotations.Methods.class,
            JetAnnotations.Functions.class,
            JetAnnotations.Tags.class,
        };
        //@formatter:on
        long ts = System.currentTimeMillis();
        Set<Class<?>> klasses = AnnotationClassLookupUtils.getClasses(scanPackages, true, annoClasses, config.isImportAutoscanSkiperrors());
        ts = System.currentTimeMillis() - ts;

        log.info("Successfully to find {} classes, cost {} ms.", klasses.size(), ts);

        for (Class<?> klass : klasses) {
            for (Annotation anno : klass.getAnnotations()) {
                if (anno instanceof JetAnnotations.Methods) {
                    resolver.addMethodClass(klass);
                } else if (anno instanceof JetAnnotations.Functions) {
                    resolver.addFunctionClass(klass);
                } else if (anno instanceof JetAnnotations.Tags) {
                    resolver.addTagClass(klass);
                }
            }
        }
    }

    private ResourceLoader createResourceLoader() {
        try {
            ResourceLoader resourceLoader;
            if (config.getCompileStrategy() == CompileStrategy.none) {
                // 这种情况下,使用自定义的 ResourceLoader
                resourceLoader = new CompiledClassResourceLoader();
            } else {
                resourceLoader = (ResourceLoader) config.getTemplateLoader().newInstance();
            }
            resourceLoader.initialize(this, config.getTemplatePath(), config.getInputEncoding());
            return resourceLoader;
        } catch (Exception e) {
            throw ExceptionUtils.uncheck(e);
        }
    }

    private JetSecurityManager createSecurityManager() {
        Class<?> klass = config.getSecurityManager();
        if (klass == null) {
            return null;
        }
        try {
            JetSecurityManager manager = (JetSecurityManager) klass.newInstance();
            manager.initialize(this);
            return manager;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private JetGlobalVariables createGlobalVariables() {
        Class<?> klass = config.getGlobalVariables();
        if (klass == null) {
            return null;
        }
        try {
            return (JetGlobalVariables) klass.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void startPreCompileTask() {
        // 启动预编译线程
        Thread thread = new Thread() {
            @Override
            public void run() {
                List<String> resources = resourceLoader.loadAll();
                log.info("Find {} templates to precompile ...", resources.size());
                int succ = 0;
                int fail = 0;
                long ts = System.currentTimeMillis();
                for (String name : resources) {
                    try {
                        getTemplate(name);
                        succ++;
                    } catch (Exception e) {
                        fail++;
                        log.error("precompile error.", e);
                    }
                }
                ts = System.currentTimeMillis() - ts;
                log.info("Completed precompile templates in {} ms, success = {}, failure = {}.", ts, succ, fail);
            }
        };
        thread.setName("JetPreCompiler");
        thread.setDaemon(true);
        thread.start();
    }

    private class ConcurrentResourceCache extends ConcurrentCache<String, Resource> {
        @Override
        protected Resource doGetValue(String name) {
            return JetEngine.this.resourceLoader.load(name);
        }
    }

    private class ConcurrentTemplateCache extends ConcurrentCache<String, JetTemplate> {
        @Override
        protected JetTemplate doGetValue(String name) {
            Resource resource = JetEngine.this.getResource(name);
            return new JetTemplate(JetEngine.this, resource);
        }
    }
}
TOP

Related Classes of jetbrick.template.JetEngine

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.