Coder Social home page Coder Social logo

Comments (7)

yingzhuo avatar yingzhuo commented on September 27, 2024

数据格式化器[实现类 1/2]

package jetbrick.template.formatter;

/**
 * 
 * 默认对象格式化器,直接调用object.toString()
 * 
 * @author 应卓([email protected])
 *
 */
public class DefaultObjectFormatter implements ObjectFormatter  {

    @Override
    public String format(Object object) {
        return object != null ? object.toString() : "";
    }

    @Override
    public boolean supports(Class<?> objectType) {
        return true;
    }

}

数据格式化器[实现类 2/2]

package jetbrick.template.formatter;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import jetbrick.template.parser.support.ClassUtils;

/**
 * 
 * 默认的java.util.Date与java.util.Calendar格式化器
 * 
 * @author 应卓([email protected])
 *
 */
public class TimeObjectFormatter implements ObjectFormatter {

    private static final DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());

    @Override
    public String format(Object object) {
        return FORMAT.format(object);
    }

    @Override
    public boolean supports(Class<?> objectType) {
        return ClassUtils.isAssignable(Date.class, objectType)          ||
                ClassUtils.isAssignable(Calendar.class, objectType);
    }

}

from jetbrick-template-1x.

yingzhuo avatar yingzhuo commented on September 27, 2024

数据格式化器的查找器[接口]

package jetbrick.template.formatter;

/**
 * 数据格式化器的查找器
 * 
 * @author 应卓([email protected])
 *
 */
public interface ObjectFormatterFinder {

    /**
     * 查找
     * 
     * @param object 要格式化的数据
     * @return 相适应的格式化器,如果有多个匹配的,只返回第一个
     */
    public ObjectFormatter find(Object object);

}

数据格式化器的查找器实现类

package jetbrick.template.formatter;

import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import jetbrick.template.JetEngine;

/**
 * 默认数据格式化器的查找器,使用缓存机制
 * 
 * @author 应卓([email protected])
 *
 */
public class DefaultObjectFormatterFinder implements ObjectFormatterFinder {

    private static final ObjectFormatter DEFAULT = new DefaultObjectFormatter();

    private final List<ObjectFormatter> objectFormatters;
    private final Map<Class<?>, ObjectFormatter> cache = new IdentityHashMap<Class<?>, ObjectFormatter>(4096);

    public DefaultObjectFormatterFinder(JetEngine jetEngine) {
        super();
        this.objectFormatters = jetEngine.getObjectFormatters();
    }

    @Override
    public ObjectFormatter find(Object object) {

        if (object == null) {
            return DEFAULT;
        }

        Class<?> klass = object.getClass();
        ObjectFormatter cached = cache.get(klass);

        if (cached != null) {
            return cached;
        } else {
            for (ObjectFormatter formatter : this.objectFormatters) {
                if (formatter.supports(klass)) {
                    cache.put(klass, formatter);
                    return formatter;
                }
            }
        }

        // 不会到这里来
        return DEFAULT;
    }

}

from jetbrick-template-1x.

yingzhuo avatar yingzhuo commented on September 27, 2024

配置项添加object.formatters 相应修改JetConfig和JetEngine

package jetbrick.template;

import java.io.File;
import java.util.List;
import java.util.Properties;
import jetbrick.template.resource.loader.FileSystemResourceLoader;
import jetbrick.template.utils.ConfigSupport;
import jetbrick.template.utils.PathUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JetConfig extends ConfigSupport<JetConfig> {
    public static final String DEFAULT_CONFIG_FILE = "jetbrick-template.properties";

    public static final String IMPORT_PACKAGES = "import.packages";
    public static final String IMPORT_CLASSES = "import.classes";
    public static final String IMPORT_METHODS = "import.methods";
    public static final String IMPORT_FUNCTIONS = "import.functions";
    public static final String IMPORT_TAGS = "import.tags";
    public static final String IMPORT_VARIABLES = "import.variables";
    public static final String INPUT_ENCODING = "input.encoding";
    public static final String OUTPUT_ENCODING = "output.encoding";
    public static final String TEMPLATE_LOADER = "template.loader";
    public static final String TEMPLATE_PATH = "template.path";
    public static final String TEMPLATE_SUFFIX = "template.suffix";
    public static final String TEMPLATE_RELOADABLE = "template.reloadable";
    public static final String COMPILE_ALWAYS = "compile.always";
    public static final String COMPILE_DEBUG = "compile.debug";
    public static final String COMPILE_PATH = "compile.path";
    public static final String TRIM_DIRECTIVE_LINE = "trim.directive.line";
    public static final String TRIM_DIRECTIVE_COMMENTS = "trim.directive.comments";
    public static final String TRIM_DIRECTIVE_COMMENTS_PREFIX = "trim.directive.comments.prefix";
    public static final String TRIM_DIRECTIVE_COMMENTS_SUFFIX = "trim.directive.comments.suffix";
    public static final String OBJECT_FORMATTERS = "object.formatters";

    private final Logger log = LoggerFactory.getLogger(JetConfig.class);

    private List<String> importPackages;
    private List<String> importClasses;
    private List<String> importMethods;
    private List<String> importFunctions;
    private List<String> importTags;
    private List<String> importVariables;
    private String inputEncoding;
    private String outputEncoding;
    private Class<?> templateLoader;
    private String templatePath;
    private String templateSuffix;
    private boolean templateReloadable;
    private boolean compileAlways;
    private boolean compileDebug;
    private String compilePath;
    private boolean trimDirectiveLine;
    private boolean trimDirectiveComments;
    private String trimDirectiveCommentsPrefix;
    private String trimDirectiveCommentsSuffix;
    private List<String> objectFormatters;

    public JetConfig() {
        // default config
        String defaultCompilePath = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath();

        Properties config = new Properties();
        config.setProperty(INPUT_ENCODING, "utf-8");
        config.setProperty(OUTPUT_ENCODING, "utf-8");
        config.setProperty(TEMPLATE_LOADER, FileSystemResourceLoader.class.getName());
        config.setProperty(TEMPLATE_PATH, PathUtils.getCurrentPath());
        config.setProperty(TEMPLATE_SUFFIX, ".jetx");
        config.setProperty(TEMPLATE_RELOADABLE, "false");
        config.setProperty(COMPILE_ALWAYS, "true");
        config.setProperty(COMPILE_DEBUG, "false");
        config.setProperty(COMPILE_PATH, defaultCompilePath);
        config.setProperty(TRIM_DIRECTIVE_LINE, "true");
        config.setProperty(TRIM_DIRECTIVE_COMMENTS, "false");
        config.setProperty(TRIM_DIRECTIVE_COMMENTS_PREFIX, "<!--");
        config.setProperty(TRIM_DIRECTIVE_COMMENTS_SUFFIX, "-->");
        load(config);
    }

    @Override
    public JetConfig build() {
        super.build();

        // log
        if (log.isInfoEnabled()) {
            log.info("Load template from \"" + templatePath + "\" by " + templateLoader + ".");
            if (templateReloadable) {
                log.info("autoload on: template will automatically reload.");
            } else {
                log.info("autoload off: template will NOT automatically reload.");
            }
        }
        return this;
    }

    public List<String> getImportPackages() {
        return importPackages;
    }

    public List<String> getImportClasses() {
        return importClasses;
    }

    public List<String> getImportMethods() {
        return importMethods;
    }

    public List<String> getImportFunctions() {
        return importFunctions;
    }

    public List<String> getImportTags() {
        return importTags;
    }

    public List<String> getImportVariables() {
        return importVariables;
    }

    public String getInputEncoding() {
        return inputEncoding;
    }

    public String getOutputEncoding() {
        return outputEncoding;
    }

    public Class<?> getTemplateLoader() {
        return templateLoader;
    }

    public String getTemplatePath() {
        return templatePath;
    }

    public String getTemplateSuffix() {
        return templateSuffix;
    }

    public boolean isTemplateReloadable() {
        return templateReloadable;
    }

    public boolean isCompileAlways() {
        return compileAlways;
    }

    public boolean isCompileDebug() {
        return compileDebug;
    }

    public String getCompilePath() {
        return compilePath;
    }

    public boolean isTrimDirectiveLine() {
        return trimDirectiveLine;
    }

    public boolean isTrimDirectiveComments() {
        return trimDirectiveComments;
    }

    public String getTrimDirectiveCommentsPrefix() {
        return trimDirectiveCommentsPrefix;
    }

    public String getTrimDirectiveCommentsSuffix() {
        return trimDirectiveCommentsSuffix;
    }

    public List<String> getObjectFormatters() {
        return objectFormatters;
    }


}
package jetbrick.template;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

import jetbrick.template.compiler.JavaCompiler;
import jetbrick.template.compiler.JetTemplateClassLoader;
import jetbrick.template.formatter.DefaultObjectFormatter;
import jetbrick.template.formatter.ObjectFormatter;
import jetbrick.template.formatter.TimeObjectFormatter;
import jetbrick.template.parser.VariableResolver;
import jetbrick.template.parser.support.ClassUtils;
import jetbrick.template.resource.Resource;
import jetbrick.template.resource.SourceCodeResource;
import jetbrick.template.resource.loader.ResourceLoader;
import jetbrick.template.utils.ConcurrentCache;
import jetbrick.template.utils.ExceptionUtils;
import jetbrick.template.utils.PathUtils;
import jetbrick.template.utils.Version;

public class JetEngine {
    public static final String VERSION = Version.getVersion(JetEngine.class);

    private final JetConfig config;
    private final ResourceLoader resourceLoader;
    private final VariableResolver resolver;
    private final JetTemplateClassLoader classLoader;
    private final JavaCompiler javaCompiler;
    private final ConcurrentResourceCache resourceCache;
    private final ConcurrentTemplateCache templateCache;
    private final List<ObjectFormatter> objectFormatters;

    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));
    }

    protected JetEngine(JetConfig config) {
        this.config = config.build();
        this.resolver = createVariableResolver();
        this.resourceLoader = createResourceLoader();
        this.classLoader = new JetTemplateClassLoader(config.getCompilePath(), config.isTemplateReloadable());
        this.javaCompiler = JavaCompiler.create(this.classLoader);
        this.resourceCache = new ConcurrentResourceCache();
        this.templateCache = new ConcurrentTemplateCache();

        // 初始化ojectFormatters
        List<ObjectFormatter> formatters = new ArrayList<ObjectFormatter>();
        for (String klassName : config.getObjectFormatters()) {
            Class<?> klass = resolver.resolveClass(klassName);

            if (klass == null) continue;

            // 用户配置错误,类型并没有实现ObjectFormatter接口
            if (! ClassUtils.isAssignable(ObjectFormatter.class, klass)) { 
                throw new ClassCastException("class '" + klass.getName() + "' is not a implemention of type '" + ObjectFormatter.class.getName() + "'");
            }

            // 创建对象
            try {
                formatters.add((ObjectFormatter) klass.newInstance());
            } catch (Exception e) {
                throw ExceptionUtils.uncheck(e);
            }
        }

        formatters.add(new TimeObjectFormatter());
        formatters.add(new DefaultObjectFormatter());
        this.objectFormatters = Collections.unmodifiableList(formatters);
    }

    /**
     * 根据一个绝对路径,判断资源文件是否存在
     */
    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;
    }

    /**
     * 直接从源代码中创建一个新的模板对象
     */
    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 getJdkCompiler() {
        return javaCompiler;
    }

    /**
     * 获取模板配置
     */
    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);
        }
        return resolver;
    }

    private ResourceLoader createResourceLoader() {
        try {
            ResourceLoader resourceLoader = (ResourceLoader) config.getTemplateLoader().newInstance();
            resourceLoader.initialize(config.getTemplatePath(), config.getInputEncoding());
            return resourceLoader;
        } catch (Exception e) {
            throw ExceptionUtils.uncheck(e);
        }
    }

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

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

    public List<ObjectFormatter> getObjectFormatters() {
        return objectFormatters;
    }

}

from jetbrick-template-1x.

yingzhuo avatar yingzhuo commented on September 27, 2024

JetWriter API变更

package jetbrick.template.runtime;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

import jetbrick.template.JetEngine;
import jetbrick.template.formatter.DefaultObjectFormatterFinder;
import jetbrick.template.formatter.ObjectFormatter;
import jetbrick.template.formatter.ObjectFormatterFinder;

public abstract class JetWriter {

    private ObjectFormatterFinder objectFormatterFinder;

    // ========================================================================
    // 应卓标记两个方法为过时
    @Deprecated
    public static JetWriter create(Writer os, String encoding) {
        throw new UnsupportedOperationException();
    }

    @Deprecated
    public static JetWriter create(OutputStream os, String encoding) {
        throw new UnsupportedOperationException();
    }
    // ========================================================================

    public static JetWriter create(JetEngine jetEngine, Writer os, String encoding) {
        return new JetWriterImpl(jetEngine, os, encoding);
    }

    public static JetWriter create(JetEngine jetEngine, OutputStream os, String encoding) {
        return new JetOutputStreamImpl(jetEngine, os, encoding);
    }

    public JetWriter(JetEngine jetEngine) {
        objectFormatterFinder = new DefaultObjectFormatterFinder(jetEngine);
    }

    public abstract boolean isStreaming();

    public abstract void print(String text, byte[] bytes) throws IOException;

    public void print(boolean x) throws IOException {
        print(x ? "true" : "false");
    }

    public void print(byte x) throws IOException {
        print(String.valueOf(x));
    }

    public void print(char x) throws IOException {
        print(String.valueOf(x));
    }

    public void print(short x) throws IOException {
        print(String.valueOf(x));
    }

    public void print(int x) throws IOException {
        print(String.valueOf(x));
    }

    public void print(long x) throws IOException {
        print(String.valueOf(x));
    }

    public void print(float x) throws IOException {
        print(String.valueOf(x));
    }

    public void print(double x) throws IOException {
        print(String.valueOf(x));
    }

    public abstract void print(byte x[]) throws IOException;

    public abstract void print(char x[]) throws IOException;

    public abstract void print(CharSequence x) throws IOException;

    public void print(Object x) throws IOException {
        if (x != null) {
            if (x instanceof byte[]) {
                print((byte[]) x);
            } else if (x instanceof char[]) {
                print((char[]) x);
            } else {
                ObjectFormatter formatter = this.objectFormatterFinder.find(x);
                print(formatter.format(x));
            }
        }
    }

    public abstract void println() throws IOException;

    public void println(boolean x) throws IOException {
        print(x);
        println();
    }

    public void println(byte x) throws IOException {
        print(x);
        println();
    }

    public void println(char x) throws IOException {
        print(x);
        println();
    }

    public void println(short x) throws IOException {
        print(x);
        println();
    }

    public void println(int x) throws IOException {
        print(x);
        println();
    }

    public void println(long x) throws IOException {
        print(x);
        println();
    }

    public void println(float x) throws IOException {
        print(x);
        println();
    }

    public void println(double x) throws IOException {
        print(x);
        println();
    }

    public void println(byte x[]) throws IOException {
        if (x != null) {
            print(x);
            println();
        }
    }

    public void println(char x[]) throws IOException {
        if (x != null) {
            print(x);
            println();
        }
    }

    public void println(CharSequence x) throws IOException {
        if (x != null) {
            print(x);
            println();
        }
    }

    public void println(Object x) throws IOException {
        if (x != null) {
            print(x);
            println();
        }
    }

    public abstract void flush() throws IOException;

    public abstract void close() throws IOException;

    static class JetWriterImpl extends JetWriter {
        private static final String NEWLINE = "\r\n";
        private final Writer os;
        private final String encoding;

        public JetWriterImpl(JetEngine jetEngine, Writer os, String encoding) {
            super(jetEngine);
            this.os = os;
            this.encoding = encoding;
        }

        @Override
        public boolean isStreaming() {
            return false;
        }

        @Override
        public void print(String text, byte[] bytes) throws IOException {
            os.write(text);
        }

        @Override
        public void print(byte x[]) throws IOException {
            if (x != null) {
                os.write(new String(x, encoding));
            }
        }

        @Override
        public void print(char x[]) throws IOException {
            if (x != null) {
                os.write(x);
            }
        }

        @Override
        public void print(CharSequence x) throws IOException {
            if (x != null) {
                os.write(x.toString());
            }
        }

        @Override
        public void println() throws IOException {
            os.write(NEWLINE);
        }

        @Override
        public void flush() throws IOException {
            os.flush();
        }

        @Override
        public void close() throws IOException {
            os.close();
        }
    }

    static class JetOutputStreamImpl extends JetWriter {
        private static final byte[] NEWLINE = new byte[] { '\r', '\n' };
        private final OutputStream os;
        private final String encoding;

        public JetOutputStreamImpl(JetEngine jetEngine, OutputStream os, String encoding) {
            super(jetEngine);
            this.os = os;
            this.encoding = encoding;
        }

        @Override
        public boolean isStreaming() {
            return true;
        }

        @Override
        public void print(String text, byte[] bytes) throws IOException {
            os.write(bytes);
        }

        @Override
        public void print(byte x[]) throws IOException {
            if (x != null) {
                os.write(x);
            }
        }

        @Override
        public void print(char x[]) throws IOException {
            if (x != null) {
                os.write(new String(x).getBytes(encoding));
            }
        }

        @Override
        public void print(CharSequence x) throws IOException {
            if (x != null) {
                os.write(x.toString().getBytes(encoding));
            }
        }

        @Override
        public void println() throws IOException {
            os.write(NEWLINE);
        }

        @Override
        public void flush() throws IOException {
            os.flush();
        }

        @Override
        public void close() throws IOException {
            os.close();
        }
    }
}

from jetbrick-template-1x.

yingzhuo avatar yingzhuo commented on September 27, 2024

由于JetWriter.create(...) API变化了,还要修改相应的 JetTemplate 和 JetTagContent

package jetbrick.template.runtime;

import jetbrick.template.JetContext;
import jetbrick.template.JetEngine;
import jetbrick.template.utils.ExceptionUtils;
import jetbrick.template.utils.UnsafeCharArrayWriter;

public abstract class JetTagContext {
    public static final Class<?>[] CLASS_ARRAY = { JetTagContext.class };
    private final JetPageContext ctx;

    public JetTagContext(JetPageContext ctx) {
        this.ctx = ctx;
    }

    public String getBodyContent() {
        UnsafeCharArrayWriter out = new UnsafeCharArrayWriter();
        String encoding = ctx.getEngine().getConfig().getOutputEncoding();
        try {
            render(ctx.getContext(), JetWriter.create(ctx.getEngine(), out, encoding));
        } catch (Throwable e) {
            throw ExceptionUtils.uncheck(e);
        }
        return out.toString();
    }

    public void writeBodyContent() {
        try {
            render(ctx.getContext(), ctx.getWriter());
        } catch (Throwable e) {
            throw ExceptionUtils.uncheck(e);
        }
    }

    public JetPageContext getPageContext() {
        return ctx;
    }

    public JetEngine getEngine() {
        return ctx.getEngine();
    }

    public JetWriter getWriter() {
        return ctx.getWriter();
    }

    public JetContext getContext() {
        return ctx.getContext();
    }

    protected abstract void render(final JetContext context, final JetWriter out) throws Throwable;
}
package jetbrick.template;

import java.io.*;
import java.util.Map;
import jetbrick.template.parser.*;
import jetbrick.template.parser.code.Code;
import jetbrick.template.parser.grammer.*;
import jetbrick.template.parser.grammer.JetTemplateParser.TemplateContext;
import jetbrick.template.resource.Resource;
import jetbrick.template.runtime.*;
import jetbrick.template.utils.ExceptionUtils;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class JetTemplate {
    private static final Logger log = LoggerFactory.getLogger(JetTemplate.class);

    private final JetEngine engine;
    private final Resource resource;
    private final String encoding;
    private final boolean reloadable;
    private final File javaSourceFile;
    private final File javaClassFile;
    private JetPage pageObject;

    protected JetTemplate(JetEngine engine, Resource resource) {
        JetConfig config = engine.getConfig();

        this.engine = engine;
        this.resource = resource;
        this.encoding = config.getOutputEncoding();
        this.reloadable = config.isTemplateReloadable();
        this.javaSourceFile = engine.getJdkCompiler().getGenerateJavaSourceFile(resource.getQualifiedClassName());
        this.javaClassFile = engine.getJdkCompiler().getGenerateJavaClassFile(resource.getQualifiedClassName());

        // compile and load
        if ((!config.isCompileAlways()) && javaClassFile.lastModified() > resource.lastModified()) {
            try {
                loadClassFile();
            } catch (Throwable e) {
                // 无法 load 的话,尝试重新编译
                log.warn(e.getClass().getName() + ": " + e.getMessage());
                log.warn("Try to recompile the template.");
                compileAndLoadClass();
            }
        } else {
            compileAndLoadClass();
        }
    }

    protected void checkLastModified() {
        if (reloadable && javaClassFile.lastModified() < resource.lastModified()) {
            synchronized (this) {
                // double check
                if (javaClassFile.lastModified() < resource.lastModified()) {
                    compileAndLoadClass();
                }
            }
        }
    }

    // 从 disk 的缓存文件中读取
    private void loadClassFile() throws Exception {
        log.info("Loading template class file: " + javaClassFile.getAbsolutePath());
        Class<?> cls = engine.getClassLoader().loadClass(resource.getQualifiedClassName());

        // 判断编码匹配
        if (!encoding.equals(cls.getDeclaredField("$ENC").get(null))) {
            throw new IllegalStateException("The encoding of last compiled template class is not " + encoding);
        }

        pageObject = (JetPage) cls.newInstance();
    }

    // 编译 source 为 class, 然后 load class
    private void compileAndLoadClass() {
        log.info("Loading template source file: " + resource.getAbsolutePath());

        // generateJavaSource
        String source = generateJavaSource(resource);
        if (log.isInfoEnabled() && engine.getConfig().isCompileDebug()) {
            StringBuilder sb = new StringBuilder(source.length() + 128);
            sb.append("generateJavaSource: ");
            sb.append(javaSourceFile.getAbsolutePath());
            sb.append("\n");
            sb.append("===========================================================================\n");
            sb.append(source);
            sb.append("\n");
            sb.append("===========================================================================");
            log.info(sb.toString());
        }
        // compile
        Class<?> cls = engine.getJdkCompiler().compile(resource.getQualifiedClassName(), source);
        log.info("generateJavaClass: " + javaClassFile.getAbsolutePath());
        try {
            pageObject = (JetPage) cls.newInstance();
        } catch (Exception e) {
            throw ExceptionUtils.uncheck(e);
        }
    }

    private String generateJavaSource(Resource resource) {
        char[] source = resource.getSource();
        ANTLRInputStream is = new ANTLRInputStream(source, source.length);
        is.name = resource.getAbsolutePath(); // set source file name, it will be displayed in error report.

        JetTemplateParser parser = new JetTemplateParser(new CommonTokenStream(new JetTemplateLexer(is)));
        parser.removeErrorListeners(); // remove ConsoleErrorListener
        parser.addErrorListener(new JetTemplateErrorListener());
        parser.setErrorHandler(new JetTemplateErrorStrategy());

        TemplateContext templateParseTree = parser.template();
        JetTemplateCodeVisitor visitor = new JetTemplateCodeVisitor(engine, engine.getVariableResolver(), parser, resource);
        Code code = templateParseTree.accept(visitor);
        return code.toString();
    }

    public void render(Map<String, Object> context, Writer out) {
        JetContext ctx = new JetContext(context);
        JetWriter writer = JetWriter.create(this.engine, out, encoding);
        render(new JetPageContext(this, ctx, writer));
    }

    public void render(Map<String, Object> context, OutputStream out) {
        JetContext ctx = new JetContext(context);
        JetWriter writer = JetWriter.create(this.engine, out, encoding);
        render(new JetPageContext(this, ctx, writer));
    }

    public void render(JetContext context, Writer out) {
        if (context.isSimpleModel()) {
            // simpleModel 的情况代表是用户自己 new 出来的 JetContext
            // 为了防止 #set 污染 context,这里重新 new 一个新的。
            context = new JetContext(context.getContext());
        }
        JetWriter writer = JetWriter.create(this.engine, out, encoding);
        render(new JetPageContext(this, context, writer));
    }

    public void render(JetContext context, OutputStream out) {
        if (context.isSimpleModel()) {
            // simpleModel 的情况代表是用户自己 new 出来的 JetContext
            // 为了防止 #set 污染 context,这里重新 new 一个新的。
            context = new JetContext(context.getContext());
        }
        JetWriter writer = JetWriter.create(this.engine, out, encoding);
        render(new JetPageContext(this, context, writer));
    }

    public void render(JetContext context, JetWriter writer) {
        render(new JetPageContext(this, context, writer));
    }

    private void render(JetPageContext ctx) {
        try {
            pageObject.render(ctx);
        } catch (Throwable e) {
            throw ExceptionUtils.uncheck(e);
        }
    }

    public JetEngine getEngine() {
        return engine;
    }

    public String getName() {
        return resource.getName();
    }
}

from jetbrick-template-1x.

subchen avatar subchen commented on September 27, 2024

Good Job.

不过下次建议用 pull request. 这个直接贴代码,太那个啥...

from jetbrick-template-1x.

yingzhuo avatar yingzhuo commented on September 27, 2024

我们公司不让我github 我只能用网页版。

from jetbrick-template-1x.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.